قالب وردپرس درنا توس
Home / IOS Development / Type your own API clients in Swift

Type your own API clients in Swift



Like many iOS developers, I used to use AFNetworking (like Swift counterpart, Alamofire) for all my networking needs. And many developers believe that the existence of such a library may mean that doing something similar is difficult or expensive. And earlier it was! NSURLConnection in iOS 6 and earlier was a pain to implement and pack everything that, in practical terms, saved you a lot of time.

The truth is that since the introduction of NSURLSession in IOS 7, networking is quite easy to do and writing your own API client can simplify your addictions. If unnecessary addictions are not enough to convince you, think about the mistakes you can introduce by including third party code that you do not understand or even the size of your binary if you include a large library just to use a small amount [1

9659003] A simple NSURLSession

I promise that NSURLSession was easy, let's take a look at one example:

  la    session    =   ] NSURLSession (configuration    NSURLRequest (URL:    NSURL (string:    "http: // yourapi.com / endpoint"    NSURLSessionConfiguration )   ) 

  la    task:!    NSURLSessionDataTask    =    session.dataTaskWithRequest (request)    {   (data,    response,    error)    ->    expires [19659000] [19659000] 19659031    [la19659006] data    =    data [19659006] {
          la    response    =    NSString (data:    data    encoding:    NSUTF8StringEncoding) 
          print (response) 
    } [19659046] 
  task.resume () 

The first of the three main components is NSURLSession which in connection with this post is not need to be specifically configured. It handles all the data or download tasks we provide, and call our blocks with the results.

Hopefully you are already familiar with NSURLRequest that contains details about the request as URL, method, some parameters, etc. The simplest configuration only takes a URL and default for the GET method.

And finally, NSURLSessionDataTask which I have only explicitly made here to illustrate. It contains the block that will burn when we get the results from the request. We get back three options: NSData containing the fast body data from the answer, a NSURLResponse object with the metadata from the answer and maybe a NSError . [19659051] Your own API client

Now that we have established our basic understanding of NSURLSession based, let's use Swift to package these basics into a single API client.

Here is the core: a simple data task package that takes a NSURLRequest and method name, and returns an indicator of success and a decoded JSON body. If you had an API that returned XML, you would change deserialization for XML instead of JSON, but the rest would be the same.

Notice the pattern matching in where the clause when checking the answer code reach for success! private func data task (request: NSMutableURLRequest, method: String, completion: (success: ] Boolean, object 😕 AnyObject) -> ()) {
request.HTTPMethod = method

la session session ] NSURLSession (configuration: NSURLSessionConfiguration.defaultSessionConfiguration ())

session.dataTaskWithRequest (request) {19659006] (data, response, error) void i
if la data = data {
la .json = [19659006] try? NSJ SONSerialization.JSONObjectWithData (data, alternatives: [])? responded = response as NSHTTPURL Response where 200. 299 ~ = Response StatusCode {
Completion (Success: True [19659006] Object: .json)
19659110]} Otherwise {
Completion (Success: false Item: .json)
} [19659044]}
}. CV ()
}

Then we can package our usual request methods into small methods that specify the HTTP method and pass through the completion block. This will give more meaning when we put everything in the end. private func post (request: NSMutableURLRequest, completion: (success: ] Boolean, item: AnyObject) -> ()) {
dataTask (request, method 😕 "post" completion: completion)
] [19659000] FUNC [Request: NSMutableURLRequest, Completion: (Success: [19659006] Boolean, Object: AnyObject -> ()) {
dataTask (request, method 😕 "PUT" [19659016] completion: completion)
[19659000] FUNC [request: NSMutableURLRequest, Completion: (success:? Boolean, AnyObject) -> Completion: Completion
} The Last Function We Want to Simplify (19659006)
DataTas k [Request Method: "GET" is the creation of a NSURLRequest with the data we will send. In this case, we encrypt the parameters as form data and provide an authorization if we have it. This method will change most from API to API, but its responsibility will remain the same. private func clientURLRequest (sti: String, params: Dictionary <String, AnyObject> = nil ] -?> NSMutableURLRequest {
la request = NSMutableURLRequest (URL: NSURL (string: "http: // api.website.com/ " + path) )
if With parameters = parameters {
was paramString = ""
to (key, value) [19659030] in parameters {
la escapedKey 19659006] = key.stringByAddingPercentEncodingWithAllowedCharacters (.URLQueryAllowedCharacterSet ())
la escapedValue = value.stringByAddingPercentEncodingWithAllowedCharacters (.URLQueryA llowedCharacterSet ()) [19659110] paramString + = " ( escapedKey ) = ( escapedValue ) and"
}

request.setValue ( " application / x-www form-urlencoded " forHTTPHeaderField: " Content-Type ")
request.HTTPBody = paramString [19659000]] ] token = token {
request.addValue ( "Bearer" + token, forHTTPHeaderField: ] "Authorization" )
}

return request
}

Finally, we can start making requests with our API client. This is a simplified login request that issues a POST request to the login email with the email and password parameters. You can access both a general success indicator and a Dictionary object that may contain relevant data in this method. func login (email: String, password: String, completion: (? Success: Boolean, message -> ()) {[19659031] loginObject = [ "e" : e-mail, "password" : password]

post (clientURLRequest ( "aut / local" parameters: loginObject)) [19659006] (success, object) -> () [19659030] in
dispatch_async (dispatch_get_main_queue (), { () -> [19659000] void i
if success {
completion (success: true message: nil )
} otherwise {[1965933 = 19659006] = ] "message" ] as String {
message = passedMessage
}
completion : true message: message)
}
}
}
}

Maybe you want to retrieve and save a token when the user is logged enter or rotate the returned data to a structure before returning it to the call method (my favorite!). These request-specific measures should be taken care of here.

We can create small features like this for each of the classes of requests we will make to our API, and customize them to provide a consistent and easy experience for the phone number (probably in a display checker somewhere). We do not need to worry about coding values ​​or generate NSURL objects because our thin wrapper addresses these issues for us.


Here's what I like about this approach:

Simple reason for

We remove some of the parts that are technically uninteresting or repetitive, but the code concepts for HTTP that you should understand are: Submit a URL , method name and parameters and get back an indicator of success and some decoded data.

Flexible for different APIs

The construction of your URL request is often the only detail that changes based on who wrote your server code. I do not always have control over how this server implementation is done as a mobile dev, so it's possible to customize this for each project that is the key.

Short and sweet

The base client is less than 50 lines of code. If I start writing a lot of boilerplate to replace an addiction, it begins to carry on me, especially when it's a tool that I'll never touch again. This is short and you will make adjustments and new methods often. You should know what's going on inside!


Use this? Something else instead? How do you write your API clients? Let us know if there is something you want to change.


Questions or comments? Find us at twitter or send a problem on github




Source link