成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

自己動(dòng)手寫一個(gè)iOS 網(wǎng)絡(luò)請(qǐng)求庫(kù)的三部曲

移動(dòng)開(kāi)發(fā) iOS
NSURLSession 是 iOS7 引入的新網(wǎng)絡(luò)請(qǐng)求接口,在 WWDC2013 中有詳細(xì)介紹,下面是描述其結(jié)構(gòu)的一頁(yè) slides:

代碼示例:https://github.com/johnlui/Swift-On-iOS/blob/master/BuildYourHTTPRequestLibrary

開(kāi)源項(xiàng)目:Pitaya,適合大文件上傳的 HTTP 請(qǐng)求庫(kù):https://github.com/johnlui/Pitaya

本系列文章中,我們將嘗試使用 NSURLSession 技術(shù)構(gòu)建一個(gè)自己的網(wǎng)絡(luò)請(qǐng)求庫(kù)。

NSURLSession 簡(jiǎn)介

NSURLSession 是 iOS7 引入的新網(wǎng)絡(luò)請(qǐng)求接口,在 WWDC2013 中有詳細(xì)介紹,下面是描述其結(jié)構(gòu)的一頁(yè) slides:

當(dāng)應(yīng)用在前臺(tái)時(shí),NSURLSession 跟 NSURLConnection 沒(méi)有什么區(qū)別,但是在程序切換到后臺(tái)之后 Background Session 就會(huì)更加靈活。

嘗試 NSURLSession

準(zhǔn)備工作

新建一個(gè)名為 BuildYourHTTPRequestLibrary 的單頁(yè)面應(yīng)用,在頁(yè)面上居中放置一個(gè)按鈕,名為 Request:

拖動(dòng)綁定 Touch Up Inside 事件:

使用 NSURLSession

在 mainButtonBeTapped 函數(shù)內(nèi)填充以下代碼:

  1. @IBAction func mainButtonBeTapped(sender: AnyObject) { 
  2. let session = NSURLSession.sharedSession() 
  3. let request = NSURLRequest(URL: NSURL(string: "http://baidu.com")!) 
  4. let task = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in 
  5. let string = NSString(data: data, encoding: NSUTF8StringEncoding) 
  6. println(string) 
  7. }) 
  8. task.resume() 
  9. }

     

 

使用成功!

感受異步

異步

改寫 mainButtonBeTapped 函數(shù)的代碼:

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

再次嘗試,兩次打印之間間隔了五秒,主線程未阻塞,證明 NSURLSession 為異步執(zhí)行。

阻塞

嘗試多次點(diǎn)擊,我們能夠看到每五秒執(zhí)行一次,直到全部執(zhí)行完畢。

NSURLSession 采用的是 “異步阻塞” 模型,即所有請(qǐng)求在發(fā)出后都進(jìn)入 2# 線程執(zhí)行,在 2# 線程內(nèi)部按照阻塞隊(duì)列模式執(zhí)行。

#p#

 

開(kāi)源項(xiàng)目:Pitaya,適合大文件上傳的 HTTP 請(qǐng)求庫(kù):https://github.com/johnlui/Pitaya

本章中,我們將一起嘗試使用一個(gè)類來(lái)封裝我們之前的代碼,并嘗試加入動(dòng)態(tài)增加 HTTP 參數(shù)(params)的功能,之后封裝出一個(gè)強(qiáng)大的接口。

 

[[135519]]

基本封裝

基礎(chǔ)準(zhǔn)備

新建一個(gè) Swift 空文件,命名為 Network.swift,在里面寫一個(gè) Network 類,之后寫一個(gè)靜態(tài)方法 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() 

修改 ViewController 中的按鈕函數(shù):

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

運(yùn)行項(xiàng)目,點(diǎn)擊按鈕,效果和之前一致。

自定義 HTTP method 和 URL

修改 request() 方法,將 HTTP 方法和 URL 傳進(jìn)去:

  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() 

修改前面的函數(shù)調(diào)用:

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

運(yùn)行項(xiàng)目,點(diǎn)擊按鈕,效果和之前一致。

使用閉包處理請(qǐng)求結(jié)果

函數(shù)是 Swift 中的一等公民,閉包可以作為函數(shù)參數(shù)和返回值,十分強(qiáng)大。下面我們就用閉包來(lái)處理網(wǎng)絡(luò)請(qǐng)求的返回值。修改 request() 方法,傳遞進(jìn)去一個(gè)閉包:

  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() 

在前面函數(shù)調(diào)用處使用閉包進(jìn)行結(jié)果處理:

 

  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) 

運(yùn)行項(xiàng)目,點(diǎn)擊按鈕,效果和之前一致。

動(dòng)態(tài)增加 Params

GET 方法

GET 方法下,params 在經(jīng)過(guò) url encode 之后直接附在 URL 末尾發(fā)送給服務(wù)器。修改 request() 方法,傳遞進(jìn)去一個(gè) params 的字典:

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

為了處理 params,我們從 Alamofire 偷來(lái)他的 params 處理函數(shù)。如果是 GET 方法,那就把處理過(guò)的 params 增加到 URL 后面。Network 類的完整代碼如下:

 

  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. let request = NSMutableURLRequest(URL: NSURL(string: newURL)!) 
  10. request.HTTPMethod = method 
  11.  
  12. let task = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in 
  13. callback(data: data, response: response , error: error) 
  14. }) 
  15. task.resume() 
  16.  
  17. // 從 Alamofire 偷了三個(gè)函數(shù) 
  18. func buildParams(parameters: [String: AnyObject]) -> String { 
  19. var components: [(String, String)] = [] 
  20. for key in sorted(Array(parameters.keys), [(String, String)] { 
  21. var components: [(String, String)] = [] 
  22. if let dictionary = value as? [String: AnyObject] { 
  23. for (nestedKey, value) in dictionary { 
  24. components += queryComponents("\(key)[\(nestedKey)]", value) 
  25. else if let array = value as? [AnyObject] { 
  26. for value in array { 
  27. components += queryComponents("\(key)", value) 
  28. else { 
  29. components.extend([(escape(key), escape("\(value)"))]) 
  30.  
  31. return components 
  32. func escape(string: String) -> String { 
  33. let legalURLCharactersToBeEscaped: CFStringRef = ":&=;+!@#$()',*" 
  34. return CFURLCreateStringByAddingPercentEscapes(nil, string, nil, legalURLCharactersToBeEscaped, CFStringBuiltInEncodings.UTF8.rawValue) as String 

修改前面的函數(shù)調(diào)用:

  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) 

http://pitayaswift.sinaapp.com/pitaya.php 是我部署的用于測(cè)試的服務(wù)端代碼,會(huì)直接返回 ?get=ooxx 中的 ooxx。運(yùn)行項(xiàng)目,點(diǎn)擊按鈕,查看效果:

POST 方法

POST 方法下有幾個(gè)協(xié)議可供選擇,此處沒(méi)有文件上傳,我們采用較簡(jiǎn)單的 application/x-www-form-urlencoded 方式發(fā)送請(qǐng)求。request() 方法增加一些代碼:

  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. let request = NSMutableURLRequest(URL: NSURL(string: newURL)!) 
  9. request.HTTPMethod = method 
  10.  
  11. if method == "POST" { 
  12. request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type"
  13. request.HTTPBody = Network().buildParams(params).dataUsingEncoding(NSUTF8StringEncoding) 
  14.  
  15. let task = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in 
  16. callback(data: data, response: response , error: error) 
  17. }) 
  18. task.resume() 

修改前面的函數(shù)調(diào)用:

  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) 

使用 POST 方式發(fā)送請(qǐng)求,同樣服務(wù)端會(huì)返回 key 為 post 的 value 的值。運(yùn)行項(xiàng)目,點(diǎn)擊按鈕,結(jié)果和前面 GET 方法的結(jié)果一致。

至此,接口封裝完成!

 

#p#

開(kāi)源項(xiàng)目:Pitaya,適合大文件上傳的 HTTP 請(qǐng)求庫(kù):https://github.com/johnlui/Pitaya

本文中,我們將一起降低之前代碼的耦合度,并使用適配器模式實(shí)現(xiàn)一層獨(dú)立于底層結(jié)構(gòu)的網(wǎng)絡(luò) API,造一個(gè)真正的網(wǎng)絡(luò)請(qǐng)求“庫(kù)”。

降低耦合度

如何降低耦合度

現(xiàn)在的清湯掛面式的代碼雖然便于理解,但是功能單一,代碼雜亂。我們一起來(lái)分析 NSURLSession 的使用過(guò)程:

構(gòu)造 NSURLRequest

確定 URL

確定 HTTP 方法(GET、POST 等)

添加特定的 HTTP 頭

填充 HTTP Body

驅(qū)動(dòng) session.dataTaskWithRequest 方法,開(kāi)始請(qǐng)求

具體實(shí)施

在 Network 下另外新建一個(gè) NetworkManager 類,將 URL、params、files 等設(shè)為成員變量,讓他們?cè)跇?gòu)造函數(shù)中初始化:

  1. class NetworkManager { 
  2.  
  3. let method: String! 
  4. let params: Dictionary let callback: (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void 
  5.  
  6. let session = NSURLSession.sharedSession() 
  7. let url: String! 
  8. var request: NSMutableURLRequest! 
  9. var task: NSURLSessionTask! 
  10.  
  11. init(url: String, method: String, params: Dictionary = Dictionary(), callback: (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void) { 
  12. self.url = url 
  13. self.request = NSMutableURLRequest(URL: NSURL(string: url)!) 
  14. self.method = method 
  15. self.params = params 
  16. self.callback = callback 

之后,將上面分析的

1. 確定 URL

2. 確定 HTTP 方法(GET、POST 等)

3. 添加特定的 HTTP 頭

4. 填充 HTTP Body

前三步封裝到一個(gè) function 中,***一步封裝到一個(gè) function 中,然后把驅(qū)動(dòng) session.dataTaskWithRequest 的代碼封裝到一個(gè) function 中:

 

  1. func buildRequest() { 
  2. if self.method == "GET" && self.params.count > 0 { 
  3. self.request = NSMutableURLRequest(URL: NSURL(string: url + "?" + buildParams(self.params))!) 
  4.  
  5. request.HTTPMethod = self.method 
  6.  
  7. if self.params.count > 0 { 
  8. request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type"
  9. func buildBody() { 
  10. if self.params.count > 0 && self.method != "GET" { 
  11. request.HTTPBody = buildParams(self.params).nsdata 
  12. func fireTask() { 
  13. task = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in 
  14. self.callback(data: data, response: response, error: error) 
  15. }) 
  16. task.resume() 

之后使用一個(gè)統(tǒng)一的方法來(lái)驅(qū)動(dòng)上面三個(gè) function,完成請(qǐng)求:

  1. func fire() { 
  2. buildRequest() 
  3. buildBody() 
  4. fireTask() 

同時(shí),不要忘了那三個(gè) parse params 的從 Alamofire 偷來(lái)的函數(shù)哦,也要放到這個(gè)類里面。至此,降低耦合的工作基本完成,接下來(lái)我們開(kāi)始封裝“網(wǎng)絡(luò)API”。

使用適配器模式封裝“網(wǎng)絡(luò)API”

理解適配器模式

適配器模式是設(shè)計(jì)模式中的一種,很容易理解:我的 APP 需要一個(gè)獲取某一個(gè) URL 返回的字符串的功能,我現(xiàn)在選擇的是 Alamofire,但是正在發(fā)展的 Pitaya 看起來(lái)不錯(cuò),我以后想替換成 Pitaya,所以我封裝了一層我自己的網(wǎng)絡(luò)接口,用來(lái)屏蔽底層細(xì)節(jié),到時(shí)候只需要修改這個(gè)類,不需要再深入項(xiàng)目中改那么多接口調(diào)用了。

適配器模式聽(tīng)起來(lái)高大上,其實(shí)這是我們?cè)谌粘>幋a中非常常用的設(shè)計(jì)模式。

Do it!

修改 Network 類的代碼為:

  1. class Network{ 
  2. static func request(method: String, url: String, params: Dictionary = Dictionary(), callback: (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void) { 
  3. let manager = NetworkManager(url: url, method: method, params: params, callback: callback) 
  4. manager.fire() 

搞定!

封裝多級(jí)接口

不帶 params 的接口:

  1. static func request(method: String, url: String, callback: (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void) { 
  2. let manager = NetworkManager(url: url, method: method, callback: callback) 
  3. manager.fire() 

兩個(gè) get 接口(帶與不帶 params):

 

  1. static func get(url: String, callback: (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void) { 
  2. let manager = NetworkManager(url: url, method: "GET", callback: callback) 
  3. manager.fire() 
  4. static func get(url: String, params: Dictionary, callback: (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void) { 
  5. let manager = NetworkManager(url: url, method: "GET", params: params, callback: callback) 
  6. manager.fire() 

兩個(gè) post 接口(帶與不帶 params):

 

  1. static func post(url: String, callback: (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void) { 
  2. let manager = NetworkManager(url: url, method: "POST", callback: callback) 
  3. manager.fire() 
  4. static func post(url: String, params: Dictionary, callback: (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void) { 
  5. let manager = NetworkManager(url: url, method: "POST", params: params, callback: callback) 
  6. manager.fire() 

測(cè)試接口

修改 ViewController 中的調(diào)用代碼,測(cè)試多級(jí) API:

 

  1. @IBAction func mainButtonBeTapped(sender: AnyObject) { 
  2. let url = "http://pitayaswift.sinaapp.com/pitaya.php" 
  3.  
  4. Network.post(url, callback: { (data, response, error) -> Void in 
  5. println("POST 1 請(qǐng)求成功"
  6. }) 
  7. Network.post(url, params: ["post""POST Network"], callback: { (data, response, error) -> Void in 
  8. let string = NSString(data: data, encoding: NSUTF8StringEncoding) as! String 
  9. println("POST 2 請(qǐng)求成功 " + string) 
  10. }) 
  11.  
  12. Network.get(url, callback: { (data, response, error) -> Void in 
  13. println("GET 1 請(qǐng)求成功"
  14. }) 
  15. Network.get(url, params: ["get""POST Network"], callback: { (data, response, error) -> Void in 
  16. let string = NSString(data: data, encoding: NSUTF8StringEncoding) as! String 
  17. println("GET 2 請(qǐng)求成功 " + string) 
  18. }) 
  19.  
  20. Network.request("GET", url: url, params: ["get""Request Network"]) { (data, response, error) -> Void in 
  21. let string = NSString(data: data, encoding: NSUTF8StringEncoding) as! String 
  22. println("Request 請(qǐng)求成功 " + string) 

運(yùn)行項(xiàng)目,點(diǎn)擊按鈕,查看效果:

 

多級(jí) API 封裝成功!

 

【責(zé)任編輯:chenqingxiang TEL:(010)68476606】

責(zé)任編輯:chenqingxiang 來(lái)源: CocoaChina
相關(guān)推薦

2015-06-02 09:51:40

iOS網(wǎng)絡(luò)請(qǐng)求封裝接口

2022-10-10 09:10:51

家庭網(wǎng)絡(luò)網(wǎng)絡(luò)

2015-06-02 10:24:43

iOS網(wǎng)絡(luò)請(qǐng)求降低耦合

2009-09-14 09:04:17

CCNA考試CCNA

2011-03-25 09:56:40

Nagios 安裝

2010-05-12 10:51:06

2011-08-03 10:33:05

網(wǎng)絡(luò)管理網(wǎng)絡(luò)拓?fù)涔芾?/a>

2010-07-17 01:12:31

Telnet服務(wù)

2010-09-26 14:39:40

DHCP故障分析

2011-03-09 09:30:52

Mina

2011-03-21 09:22:46

Tomcat

2013-06-28 09:35:04

Hypervisor虛擬化成本

2010-09-06 09:22:26

CSS語(yǔ)法

2015-05-12 10:42:53

程序員代碼

2012-09-10 16:19:00

云計(jì)算公共云

2017-02-07 14:50:39

華為

2017-04-11 09:07:20

互聯(lián)網(wǎng)

2018-03-18 15:51:59

人工智能潛力首席數(shù)據(jù)官

2018-03-19 09:35:37

人工智能

2009-04-07 11:07:16

網(wǎng)絡(luò)營(yíng)銷
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 国产精品中文字幕在线 | 国产精品欧美一区二区三区不卡 | 久久久久久久久久影视 | 一级黄色夫妻生活 | 国产高清精品一区二区三区 | 91精品国产91久久久久游泳池 | 亚洲精品一区二区三区在线 | 国产精品福利视频 | 91精品国产综合久久久久蜜臀 | 欧美一级三级在线观看 | 国产精品免费视频一区 | 久久精品色欧美aⅴ一区二区 | 国产草草视频 | 99只有精品 | 亚洲视频免费播放 | 在线一区观看 | 欧美日韩亚洲国产 | 欧美日韩视频在线第一区 | 亚洲精品一区在线观看 | 国产成人免费视频 | 欧美乱操| 国产一区二区三区四区 | 欧美视频成人 | 午夜精品久久久久久久久久久久久 | 日韩电影中文字幕 | 黄色大片免费看 | 91精品国产91久久久久久吃药 | 中文字幕在线观看精品 | 久久高潮 | 欧美精品一区二区免费视频 | 日本天堂一区二区 | 美女在线观看国产 | 在线观看亚 | 成人av免费 | 成人精品一区二区三区 | 日本不卡一区二区三区在线观看 | 国产成人在线视频 | 久久综合久久自在自线精品自 | 国产精品一区二区三区四区 | 午夜视频网站 | 99re在线视频 |