Active Filters: Standard Setup

Last week we in Bite #223 and #224 we covered an example "Standard Setup" for new apps. Since those Bites were published, readers have been asking many questions, requesting more information about how all these things fit together.

Today we'll answer one of those questions in more depth: Authentication. Let's dive in.

Who? Again it's me, Jake Marsh! I write this thing.

Like we covered before, the heart of our HTTP "stack" is built around the Moya framework (Bite #150). One of the neat parts about Moya is how it lets us customize how it works. One way is through an "request closure". As the name implies, this closure's job is to create the actual NSURLRequest that will be sent.

Here's an example implementation. Inside we can set HTTP headers, and modify the URL request in any way we want. This makes adding authentication super simple.
Here we set a "Bearer" token as the Authorization header.

let requestClosure = { (endpoint: RxMoya.Endpoint<StewardAPI>, done: NSURLRequest -> Void) in
  let request = endpoint.urlRequest.mutableCopy() as! NSMutableURLRequest

  if let token = SharedKeycard.token {
    request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
  }

  done(request)
}

The SharedKeycard is simply a singleton that holds the auth token:

func lookForTokenInKeychain() -> String? { /* not important */ }

public class Keycard : NSObject {
  public var token: String? = nil

  public override init() {
    super.init()    
    token = lookForTokenInKeychain()
  }
}

public let SharedKeycard = Keycard()

Finally, we simply pass in our custom request closure when creating our Moya "provider":

let StewardAPI = RxMoyaProvider<StewardAPI>(
  requestClosure: requestClosure
)

A quick shout out to reader Justin Williams who wrote in asking for more information about how authentication fits into this puzzle.

Have any questions about how all this fits together? Want to see some other developer's example setup? Don't be shy! hello@littlebitesofcocoa.com. Any and all comments/questions are welcome!

Topics

#224: Standard Architecture 🏣

Topics

After Bite #223's "Standard Setup", many readers asked for more detail about the actual architecture involved. Today we'll take a look at an example request, model, and a bit of how data "flows" from the web in to views in the app.

Who? Again it's me, Jake Marsh! I write this thing. Writing in the first person feels quite strange at this point.

Let's start with a Moya setup for one endpoint. I love this convention. It standardizes "what goes where" for HTTP verbs, params, etc. I'm never trying invent, just define it, and move on.

public enum StewardAPI : RxMoya.TargetType {
  case Checkins(start: Int)
}

extension StewardAPI {
  public var method: RxMoya.Method { return .GET }
}

extension StewardAPI {
  public var path: String {
    switch self {
      case .Checkins: return "/checkins"
    }
  }
}

extension StewardAPI {
  public var parameters: [String: AnyObject]? {
    switch self {
    case .Checkins(let start):
      return ["start": start, "maxResults" : 50]

Next, to actually use this API, I have an small extension I add with a global function called fetch. This returns an Observable<Decodable>.

This "calls" the HTTP endpoint, and expects some JSON that can be transformed into one of my defined Decodable types:

fetch(.Checkins(start: start), type: [Checkin].self).subscribe { event in
  switch event {
    case .Next(let checkins): print(checkins)
    case .Error(let error): print(error)
    default: break
  }
}.addDisposableTo(rx_disposeBag)

Normally, I wouldn't switch here, I'd map this into a type I use called a "Presenter" (people also call it a "Decorator" or a "View Model").

It is immutable and contains boring business logic. This is what actually gets handed to my view controllers and views:

fetch(.Checkins(start: start), type: [Checkin].self)
  .map { ListItemPresenter(item: $0) }

Please send any questions about any of this to hello@littlebitesofcocoa.com. Happy to go in to further detail if there is interest here.

Topics

#223: Standard Setup 🛠💭

Topics

Everyone does their iOS development a little bit differently. Today we'll take a look at one developer's example "default" depdency setup and describe the choices within. Let's get started.

Who? It's me, Jake Marsh! I write this thing.

I use Moya for all of my network requests. It's a fantastic tool that allows you to abstract your requests away using Swift enum cases. Associated values are used to pass in params. Love the convention this offers, feels like Swift on Rails. Moya was covered in Bite #150.

For my JSON decoding I like Decodable at the moment, it again offers a nice convention of "define a type, define its deserialization below". I also like how it uses native Swift errors combined with Optionals to gracefully fallback when deserializing. Decodable was covered in Bite #86.

I use HanekeSwift for image downloading/caching, it's fast and lightweight. I use RxSwift (Bite #162) for reactive things. I prefer its API over Reactive Cocoa (Bite #127). Both are great. Use what you like.

Who's standard setup do you want to see? Send it in: hello@littlebitesofcocoa.com