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

Brand marketing strategy: random event marketing gameplay

This kind of random event marketing method has ne...

Protecting Northeast China's black soil and safeguarding China's "rice bowl"

Produced by | Science Popularization China Author...

43 years just for a cow?

There is such a cow It was born in the Ulagai gra...

Does “cancer constitution” really exist?

Some time ago, a report about a 65-year-old woman...

Practical application of Internet finance: Who touched your promotion fees?

If you are attracting new customers for an Intern...

Please save these tips for achieving mobile app user growth!

When traffic and users in various industries are ...

10 Things iOS Users Can Make Fun of Android for Now

[[131273]] The battle between Android and iOS dev...

Dongchedi: Analysis report on car users' purchasing behavior in November 2019

On January 2, the China Automobile Dealers Associ...

Talking about IP operation from the perspective of Perfect Diary’s marketing

Nowadays, with the continuous development of bran...

How to come up with a good title, here are 5 key points to refer to

The first set of data : As of April 2017, the num...

Dialogue on Innovation—51CTO’s first developer competition has started!

/* Live to change the world Here, every work may ...

Will this winter be colder?

summary Since this autumn (September 1 to October...