swift - Singleton pattern and proper use of Alamofire's URLRequestConvertible -


this 2 part question first similar question here: proper usage of alamofire's urlrequestconvertible. need little more help!

1) create enum router implements urlrequestconvertible each model in model layer?

the alamofire github page provides example of router i've copied here:

  enum router: urlrequestconvertible {     static let baseurlstring = "http://example.com"     static var oauthtoken: string?      case createuser([string: anyobject])     case readuser(string)     case updateuser(string, [string: anyobject])     case destroyuser(string)      var method: alamofire.method {         switch self {         case .createuser:             return .post         case .readuser:             return .get         case .updateuser:             return .put         case .destroyuser:             return .delete         }     }      var path: string {         switch self {         case .createuser:             return "/users"         case .readuser(let username):             return "/users/\(username)"         case .updateuser(let username, _):             return "/users/\(username)"         case .destroyuser(let username):             return "/users/\(username)"         }     }      // mark: urlrequestconvertible      var urlrequest: nsurlrequest {         let url = nsurl(string: router.baseurlstring)!         let mutableurlrequest = nsmutableurlrequest(url: url.urlbyappendingpathcomponent(path))         mutableurlrequest.httpmethod = method.rawvalue          if let token = router.oauthtoken {             mutableurlrequest.setvalue("bearer \(token)", forhttpheaderfield: "authorization")         }          switch self {         case .createuser(let parameters):             return alamofire.parameterencoding.json.encode(mutableurlrequest, parameters: parameters).0         case .updateuser(_, let parameters):             return alamofire.parameterencoding.url.encode(mutableurlrequest, parameters: parameters).0         default:             return mutableurlrequest         }     } } 

when @ (i'm new @ swift please bear me >_<) see operations on user object; creating user, updating user etc... so, if had model objects person, company, location in model layer, create router each model object?

2) when interacting heavily api, i'm used creating "network manager" singleton abstract away network layer , hold headers , baseurl api. alamofire has "manager" described here:

top-level convenience methods alamofire.request use shared instance of alamofire.manager, configured default nsurlsessionconfiguration. such, following 2 statements equivalent:

alamofire.request(.get, "http://httpbin.org/get")  let manager = alamofire.manager.sharedinstance manager.request(nsurlrequest(url: nsurl(string: "http://httpbin.org/get"))) 

is manager should using singleton? if so, how set baseurl on manager? also, if use manager / can work router construct shown above (with each model object setting it's baseurl , nsurlrquest)? if can provide simple example?

i'm new alamofire library , swift. so, know there lot of holes in understanding i'm trying understand best can! info helps. thanks.

these questions. let me attempt answer each 1 in turn.

do create enum router implements urlrequestconvertible each model in model layer?

this great question , unfortunately there's no 1 perfect answer. there ways extend router pattern accommodate multiple object types. first option add more cases support object type. however, gets hairy pretty when more 6 or 7 cases. switch statements start out-of-control. therefore, wouldn't recommend approach.

another way approach problem introducing generics router.

routerobject protocol

protocol routerobject {     func createobjectpath() -> string     func readobjectpath(identifier: string) -> string     func updateobjectpath(identifier: string) -> string     func destroyobjectpath(identifier: string) -> string } 

model objects

struct user: routerobject {     let rootpath = "/users"      func createobjectpath() -> string { return rootpath }     func readobjectpath(identifier: string) -> string { return "\(rootpath)/\(identifier)" }     func updateobjectpath(identifier: string) -> string { return "\(rootpath)/\(identifier)" }     func destroyobjectpath(identifier: string) -> string { return "\(rootpath)/\(identifier)" } }  struct company: routerobject {     let rootpath = "/companies"      func createobjectpath() -> string { return rootpath }     func readobjectpath(identifier: string) -> string { return "\(rootpath)/\(identifier)" }     func updateobjectpath(identifier: string) -> string { return "\(rootpath)/\(identifier)" }     func destroyobjectpath(identifier: string) -> string { return "\(rootpath)/\(identifier)" } }  struct location: routerobject {     let rootpath = "/locations"      func createobjectpath() -> string { return rootpath }     func readobjectpath(identifier: string) -> string { return "\(rootpath)/\(identifier)" }     func updateobjectpath(identifier: string) -> string { return "\(rootpath)/\(identifier)" }     func destroyobjectpath(identifier: string) -> string { return "\(rootpath)/\(identifier)" } } 

router

let baseurlstring = "http://example.com" var oauthtoken: string?  enum router<t t: routerobject>: urlrequestconvertible {     case createobject(t, [string: anyobject])     case readobject(t, string)     case updateobject(t, string, [string: anyobject])     case destroyobject(t, string)      var method: alamofire.method {         switch self {         case .createobject:             return .post         case .readobject:             return .get         case .updateobject:             return .put         case .destroyobject:             return .delete         }     }      var path: string {         switch self {         case .createobject(let object, _):             return object.createobjectpath()         case .readobject(let object, let identifier):             return object.readobjectpath(identifier)         case .updateobject(let object, let identifier, _):             return object.updateobjectpath(identifier)         case .destroyobject(let object, let identifier):             return object.destroyobjectpath(identifier)         }     }      // mark: urlrequestconvertible      var urlrequest: nsmutableurlrequest {         let url = nsurl(string: baseurlstring)!         let mutableurlrequest = nsmutableurlrequest(url: url.urlbyappendingpathcomponent(path))         mutableurlrequest.httpmethod = method.rawvalue          if let token = oauthtoken {             mutableurlrequest.setvalue("bearer \(token)", forhttpheaderfield: "authorization")         }          switch self {         case .createobject(_, let parameters):             return alamofire.parameterencoding.json.encode(mutableurlrequest, parameters: parameters).0         case .updateobject(_, _, let parameters):             return alamofire.parameterencoding.url.encode(mutableurlrequest, parameters: parameters).0         default:             return mutableurlrequest         }     } } 

example usage

func exampleusage() {     let urlrequest = router.createobject(location(), ["address": "1234 road of awesomeness"]).urlrequest     alamofire.request(urlrequest)         .response { request, response, data, error in             print(request)             print(response)             print(data)             print(error)     } } 

now there few tradeoffs have make here. first off, model objects need conform routerobject protocol. otherwise router has no idea use path. also, you'll need make sure paths can constructed single identifier. if cannot, design might not work. last issue cannot store baseurl or oauthtoken directly inside router enum. unfortunately, static , stored properties not yet supported in generic enumerations.

regardless, valid way avoid having create router every model object.

should alamofire.manager.sharedinstance used singleton networkmanager instance?

it used in fashion. depends upon use case , how have designed network access. depends on how many different types of sessions need. if need background sessions , default sessions, still need concept of networkmanager contains each custom manager instance. however, if hitting network default session, sharedinstance sufficient.

how baseurl of alamofire singleton used in conjunction router pattern?

good question...the code below 1 example of how done.

alamofire manager extension

extension manager {     static let baseurlstring = "http://example.com"     static var oauthtoken: string? } 

router urlrequestconvertible updates

var urlrequest: nsmutableurlrequest {     let url = nsurl(string: alamofire.manager.baseurlstring)!     let mutableurlrequest = nsmutableurlrequest(url: url.urlbyappendingpathcomponent(path))     mutableurlrequest.httpmethod = method.rawvalue      if let token = alamofire.manager.oauthtoken {         mutableurlrequest.setvalue("bearer \(token)", forhttpheaderfield: "authorization")     }      switch self {     case .createobject(_, let parameters):         return alamofire.parameterencoding.json.encode(mutableurlrequest, parameters: parameters).0     case .updateobject(_, _, let parameters):         return alamofire.parameterencoding.url.encode(mutableurlrequest, parameters: parameters).0     default:         return mutableurlrequest     } } 

hopefully helps shed light. best of luck!


Comments

Popular posts from this blog

toolbar - How to add link to user registration inside toobar in admin joomla 3 custom component -

linux - disk space limitation when creating war file -