Write an iOS network request library by yourself - encapsulation interface

Write an iOS network request library by yourself - encapsulation interface

Code example: https://github.com/johnlui/Swift-On-iOS/blob/master/BuildYourHTTPRequestLibrary

Open source project: Pitaya, an HTTP request library suitable for uploading large files: https://github.com/johnlui/Pitaya

In this article, we will try to use a class to encapsulate our previous code, try to add the function of dynamically adding HTTP parameters (params), and then encapsulate a powerful interface.

[[135523]]

Basic package

Basic preparation

Create a new empty Swift file, name it Network.swift, write a Network class in it, and then write a static method request():

  1. class Network{
  2. static func request() {
  3. let session = NSURLSession .sharedSession()
  4. let request = NSURLRequest (URL: NSURL(string: "http://baidu.com")!)
  5. let task = session .dataTaskWithRequest(request, completionHandler: { (data, response, error) - > Void in
  6. println("just wait for 5 seconds!")
  7. sleep(5)
  8. let string = NSString (data: data, encoding: NSUTF8StringEncoding)
  9. println(string)
  10. })
  11. task.resume()
  12. }
  13. }

Modify the button function in ViewController:

  1. @IBAction func mainButtonBeTapped(sender: AnyObject) {
  2. Network.request()
  3. }

Run the project and click the button. The effect is the same as before.

Custom HTTP method and URL

Modify the request() method and pass in the HTTP method and URL:

  1. static func request(method: String, url: String) {
  2. let session = NSURLSession.sharedSession()
  3. let request = NSMutableURLRequest(URL: NSURL(string: url)!)
  4. request.HTTPMethod = method
  5. let task = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
  6. println( "just wait for 5 seconds!" )
  7. sleep( 5 )
  8. let string = NSString(data: data, encoding: NSUTF8StringEncoding)
  9. println(string)
  10. })
  11. task.resume()
  12. }

Modify the previous function call:

  1. @IBAction func mainButtonBeTapped(sender: AnyObject) {
  2. Network.request( "GET" , url: "http://baidu.com" )
  3. }

Run the project and click the button. The effect is the same as before.

Use closures to handle request results

Functions are first-class citizens in Swift. Closures can be used as function parameters and return values, which is very powerful. Next, we use closures to process the return value of network requests. Modify the request() method and pass in a closure:

  1. static func request(method: String, url: String, callback: (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void) {
  2. let session = NSURLSession.sharedSession()
  3. let request = NSMutableURLRequest(URL: NSURL(string: url)!)
  4. request.HTTPMethod = method
  5. let task = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
  6. callback(data: data, response: response, error: error)
  7. })
  8. task.resume()
  9. }

Use closures to process results in the previous function call:

  1. @IBAction func mainButtonBeTapped(sender: AnyObject) {
  2. Network.request( "GET" , url: "http://baidu.com" ) { (data, response, error) -> Void in
  3. println( "just wait for 5 seconds!" )
  4. sleep( 5 )
  5. let string = NSString(data: data, encoding: NSUTF8StringEncoding)
  6. println(string)
  7. }
  8. }

Run the project and click the button. The effect is the same as before.

Dynamically add Params

GET method

Under the GET method, params is directly attached to the end of the URL after being url-encoded and sent to the server. Modify the request() method and pass in a params dictionary:

  1. static func request(method: String, url: String, params: Dictionary = Dictionary(), callback: (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void) {
  2. ... ...
  3. }

To process params, we steal the params processing function from Alamofire. If it is a GET method, then add the processed params to the end of the URL. The complete code of the Network class is as follows:

  1. class Network{
  2. static func request(method: String, url: String, params: Dictionary = Dictionary(), callback: (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void) {
  3. let session = NSURLSession.sharedSession()
  4.  
  5. var newURL = url
  6. if method == "GET" {
  7. newURL += "?" + Network().buildParams(params)
  8. }
  9.  
  10. let request = NSMutableURLRequest(URL: NSURL(string: newURL)!)
  11. request.HTTPMethod = method
  12.  
  13. let task = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
  14. callback(data: data, response: response, error: error)
  15. })
  16. task.resume()
  17. }
  18.  
  19. // Three functions stolen from Alamofire  
  20. func buildParams(parameters: [String: AnyObject]) -> String {
  21. var components: [(String, String)] = []
  22. for key in sorted(Array(parameters.keys), [(String, String)] {
  23. var components: [(String, String)] = []
  24. if let dictionary = value as? [String: AnyObject] {
  25. for (nestedKey, value) in dictionary {
  26. components += queryComponents( "\(key)[\(nestedKey)]" , value)
  27. }
  28. } else   if let array = value as? [AnyObject] {
  29. for value in array {
  30. components += queryComponents( "\(key)" , value)
  31. }
  32. } else {
  33. components.extend([(escape(key), escape( "\(value)" ))])
  34. }
  35.  
  36. return components
  37. }
  38. func escape(string: String) -> String {
  39. let legalURLCharactersToBeEscaped: CFStringRef = ":&=;+!@#$()',*"  
  40. return CFURLCreateStringByAddingPercentEscapes(nil, string, nil, legalURLCharactersToBeEscaped, CFStringBuiltInEncodings.UTF8.rawValue) as String
  41. }
  42. }

Modify the previous function call:

  1. @IBAction func mainButtonBeTapped(sender: AnyObject) {
  2. Network.request( "GET" , url: "http://pitayaswift.sinaapp.com/pitaya.php" , params: [ "get" : "Network" ]) { (data, response, error) -> Void in
  3. let string = NSString(data: data, encoding: NSUTF8StringEncoding)
  4. println(string)
  5. }
  6. }

http://pitayaswift.sinaapp.com/pitaya.php is the server code I deployed for testing, which will directly return ooxx in ?get=ooxx. Run the project and click the button to see the effect:

POST method

There are several protocols to choose from under the POST method. There is no file upload here, so we use the simpler application/x-www-form-urlencoded method to send the request. Add some code to the request() method:

  1. static func request(method: String, url: String, params: Dictionary = Dictionary(), callback: (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void) {
  2. let session = NSURLSession.sharedSession()
  3.  
  4. var newURL = url
  5. if method == "GET" {
  6. newURL += "?" + Network().buildParams(params)
  7. }
  8.  
  9. let request = NSMutableURLRequest(URL: NSURL(string: newURL)!)
  10. request.HTTPMethod = method
  11.  
  12. if method == "POST" {
  13. request.addValue( "application/x-www-form-urlencoded" , forHTTPHeaderField: "Content-Type" )
  14. request.HTTPBody = Network().buildParams(params).dataUsingEncoding(NSUTF8StringEncoding)
  15. }
  16.  
  17. let task = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
  18. callback(data: data, response: response, error: error)
  19. })
  20. task.resume()
  21. }

Modify the previous function call:

  1. @IBAction func mainButtonBeTapped(sender: AnyObject) {
  2. Network.request( "POST" , url: "http://pitayaswift.sinaapp.com/pitaya.php" , params: [ "post" : "Network" ]) { (data, response, error) -> Void in
  3. let string = NSString(data: data, encoding: NSUTF8StringEncoding)
  4. println(string)
  5. }
  6. }

Use POST to send a request, and the server will also return the value of the key post. Run the project and click the button. The result is the same as the previous GET method.

At this point, the interface encapsulation is completed!

<<:  Three steps to write an iOS network request library yourself

>>:  Write an iOS network request library yourself - reduce coupling

Recommend

If a tool app wants to transform, what should the operators do?

Meitu was cashed out by early-stage investment in...

Practical skills to get high scores on interview questions

The live broadcast room of Qianliao’s old secretar...

Is Microsoft Edge slower than Chrome? Test results released

Yesterday, Microsoft pushed Build 10240 to users,...

Where does the back of the belly button lead to?

Follow "Body Code Decoding Bureau" (pub...

Julien "Tengame" RSD video tutorial

Julien's "Tengame" tutorial introdu...

How to do soft promotion for APP operation?

Have you noticed that there is a new business rec...

Seven Xcode tips every developer should know

If you want to do your work well, you must first ...