Alamofire-初探

對於iOS開發者來講,AFNetworking是咱們你們所熟知的,而Alamofire呢?Alamofire框架其實就是AFNetworking兄弟,出自於同一個做者。既是同一個做者,那麼他們的使用方法,框架結構上應該也是保持一致的。AFNetworkingAlamofiregit

1、網絡請求步驟

  1. 設置請求url
  2. 設置URLRequest對象,配置請求相關信息
  3. 建立會話配置URLSessionConfiguration
  4. 建立會話URLSession
  5. 建立任務和設置請求回調,併發起請求

通常經過以上幾個步來完成網絡請求,固然要根據不一樣應用場景來配置請求屬性。github

2、體驗

發起一個請求:json

func responseData() {
    let url = "http://onapp.yahibo.top/public/?s=api/test/list"
    Alamofire.request(url).responseJSON {
        (response) in
        switch response.result{
        case .success(let json):
            print("json:\(json)")
            let dict = json as! Dictionary<String, Any>
            let list = dict["data"] as! Array<AnyObject>
            guard let result = [UserModel1].deserialize(from: list) else{return}
            self.observable.onNext(result as [Any])
            break
        case .failure(let error):
            print("error:\(error)")
            break
        }
    }
}
複製代碼
  • responseJSON爲相應類型,指定爲json數據類型
  • responseAlamofire對服務器響應結果的封裝
  • 使用常規解包獲取數據headimg
  • 經過HandyJSON轉換爲模型數據,供UI展現

直接經過Alamofire發起請求經過一個閉包返回請求結果,不須要二次封裝使用簡單。這裏咱們沒有標明請求類型,沒有請求參數,那Alamofire是如何封裝這些請求參數的呢,點擊進入查看方法定義:swift

public func request( _ url: URLConvertible, method: HTTPMethod = .get, parameters: Parameters? = nil, encoding: ParameterEncoding = URLEncoding.default, headers: HTTPHeaders? = nil)
    -> DataRequest
{
    return SessionManager.default.request(
        url,
        method: method,
        parameters: parameters,
        encoding: encoding,
        headers: headers
    )
}
複製代碼

這裏已經提供了請求所須要的參數,並設置了默認值,所以外界在沒有指定方法時默認爲get方式。根據實際開發需求設置響應的參數:api

Alamofire.request(url,method: .post,parameters: ["page":"1","size":"20"]).responseJSON
複製代碼

這是咱們開發中常見的設置請求方式,請求參數,這裏的url支持多種數據類型,能夠是String、URL、URLRequest等類型,爲何這麼設計呢?由於在項目中可能當前咱們跟前有一個String類型的鏈接,也有多是個URL類型的鏈接,這時候在不須要轉換的狀況下就能夠直接使用,方便快捷,更加靈活。數組

效果以下:緩存

Alamofire.gif

3、URLSession

一樣在Alamofire中也是對URLSession封裝的,在OC中爲NSURLSession,實際上是同樣的。通常網絡請求分三個步驟:安全

一、設置URL請求地址
let url = URL.init(string: "協議://主機地址/路徑/參數1&參數2")!
複製代碼
  • 協議:指定http協議仍是https協議
  • 主機:即服務器地址ip地址或綁定ip的域名
  • 路徑:項目在服務器上的位置
  • 參數:即get參數拼接在鏈接上
二、設置URLRequest屬性
var request  = URLRequest.init(url: url)
request.httpMethod = HTTPMethod.post.rawValue
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let postData = ["username":"hibo","password":"123456"]
request.httpBody = try?JSONSerialization.data(withJSONObject: postData, options: [])
request.timeoutInterval = 30
request.cachePolicy = .useProtocolCachePolicy
複製代碼
  • httpMethod設置請求方式postget
  • setValue設置請求頭信息
  • httpBody設置請求參數,參數打包在請求體中
  • timeoutInterval設置請求超時時間
  • cachePolicy設置網絡請求緩存策略

經過以上的參數設置,可以感覺到發送一次請求是多麼不容易,所以網絡請求是必需要被封裝的服務器

三、發起請求
URLSession.shared.dataTask(with: request) { (data, response, error) in
    print("*******網絡請求*******")
    do {
        let list =  try JSONSerialization.jsonObject(with: data!, options: .allowFragments)
        print(list)
    }catch{
        print(error)
    }
}.resume()
複製代碼
  • URLSession.shared爲全局共享單例會話對象
  • 調用dataTask建立網絡請求任務
  • resume默認爲掛起狀態,調用從新啓動網絡請求任務
  • data:請求到的數據流,經過JSONSerialization序列化爲json格式使用

4、URLSessionConfiguration

URLSession.shared中內部已經配置了該項,此項爲會話配置項,通常使用都會進行配置以適用於不一樣場景。查看該類以下:cookie

open class var `default`: URLSessionConfiguration { get }
open class var ephemeral: URLSessionConfiguration { get }
@available(iOS 8.0, *)
open class func background(withIdentifier identifier: String) -> URLSessionConfiguration 複製代碼
  • default:默認模式,經常使用模式,在該模式下系統會建立持久化緩存,並在用戶的鑰匙串中保存證書
  • ephemeral:不支持持久性存儲,全部內容的會隨着session的生命週期結束而釋放
  • background:與default模式相似,在該模式下會建立一個獨立線程來傳輸網絡請求數據,能夠在後臺乃至APP關閉的時候也能夠進行數據傳輸

建立一個會話:

let configuration = URLSessionConfiguration.background(withIdentifier: "request_id")
let session = URLSession.init(configuration: configuration, delegate: self, delegateQueue: OperationQueue.main)
session.dataTask(with: request) { (data, response, error) in
    print("*******網絡請求*******")
    do {
        let list =  try JSONSerialization.jsonObject(with: data!, options: .allowFragments)
        print(list)
    }catch{
        print(error)
    }
}.resume()
複製代碼
  • 設置一個惟一會話標識,經過標識來區分不一樣的會話任務
  • 遵循URLSessionDelegate代理,實現代理方法,在本類中監控任務進度

下載任務:

let configuration = URLSessionConfiguration.background(withIdentifier: "request_id")
let session = URLSession.init(configuration: configuration, delegate: self, delegateQueue: OperationQueue.main)
session.downloadTask(with: url).resume()
複製代碼

**注意在使用background模式時必定要開啓後臺下載權限,不然沒法完成後臺下載並回調數據。**須要如下兩步才能完成:

一、開啓後臺下載權限

var backgroundHandler: (()->Void)? = nil
//設置此處開啓後臺下載權限
func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
    self.backgroundHandler = completionHandler
}
複製代碼

二、實現SessionDelegate代理方法,調用閉包方法,通知系統更新屏幕

func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
    print("後臺任務下載回來")
    DispatchQueue.main.async {
        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate, let backgroundHandle = appDelegate.backgroundHandler else { return }
        backgroundHandle()
    }
}
複製代碼

蘋果官方給出須要實現以上兩個方法來完成後臺下載,通知系統及時更新屏幕。官方文檔

5、相關屬性

官方文檔

一、常規屬性

  • identifier:配置對象的後臺會話標識符
  • httpAdditionalHeaders:與請求一塊兒發送的附加頭文件字典
  • networkServiceType:網絡服務的類型
  • allowsCellularAccess:一個布爾值,用因而否應經過蜂窩網絡進行鏈接
  • timeoutIntervalForRequest:等待附加數據的超時時間
  • timeoutIntervalForResource:資源請求容許的最大時間範圍
  • sharedContainerIdentifier:應將後臺URL會話中的文件下載到的共享容器的標識符
  • waitsForConnectivity:一個布爾值,指示會話是否應等待鏈接變爲可用仍是當即失敗

二、設置Cookie策略

  • httpCookieAcceptPolicy:決定什麼時候接受cookie的策略常量
  • httpShouldSetCookies:一個布爾值,肯定請求是否包含來自cookie存儲區的cookie
  • httpCookieStorage:用於會話中存儲cookiecookie存儲區
  • HTTPCookie:該對象爲不可變對象,從包含cookie屬性的字典初始化,支持兩個不一樣的cookie版本,v0、v1

三、設置安全策略

  • TLS協議:用於在兩個通訊應用程序之間提供保密性和數據完整性
  • tlsMaximumSupportedProtocol:在此會話中創建鏈接時客戶端應請求的最大TLS協議版本
  • tlsMinimumSupportedProtocol:協議協商期間應接受的最小TLS協議
  • urlCredentialStorage:爲身份驗證提供憑據的憑據存儲區

四、設置緩存策略

  • urlCache:用於爲會話中的請求提供緩存響應的URL緩存
  • requestCachePolicy:決定什麼時候從緩存中返回響應的預約義常量

五、支持後臺轉移

  • sessionSendsLaunchEvents:一個布爾值,指示當傳輸完成時,應用程序應在後臺恢復仍是啓動
  • isDiscretionary:一個布爾值,用於肯定後臺任務是否能夠由系統自行安排已得到最佳性能
  • shouldUseExtendedBackgroundIdleMode:一個布爾值,指示當應用程序轉移到後臺時是否應保持TCP鏈接打開

六、支持自定義協議

  • protocolClasses:在會話中處理請求的額外協議子類的數組
  • URLProtocol:該對象用來處理加載協議特定URL數據

七、支持多路徑TCP

  • multipathServiceType:指定用於經過Wi-Fi和蜂窩接口傳輸數據的多路徑TCP鏈接策略的服務類型

八、設置HTTP策略和代理屬性

  • httpMaximumConnectionsPerHost:同時鏈接到給定主機的最大數量
  • httpShouldUsePipelining:一個布爾值,用於肯定會話是否使用HTTP流水線
  • connectionProxyDictionary:包含相關要在此會話中使用的代理信息的字典

九、支持鏈接更改

  • waitsForConnectivity:一個布爾值,指示會話應等待鏈接可用仍是當即失敗

一個請求任務就有如此多的配置屬性,可想而知對一個網絡框架的整合,工做量也是很是大的。接下來咱們就一步步來了解一下Alamofire是如何一步步整合的。

相關文章
相關標籤/搜索