Alamofire - 優雅的處理 Swift 中的網絡操作

網絡處理,應該是我們平時開發的時候最常用到的操作。比如讀取 JSON 數據,下載圖片,這些操作都要和網絡打交道,一個高效穩定的網絡操作庫對於提升我們日常的開發效率有着非常關鍵的作用。Alamofire 正是這樣一個庫,成熟,穩定,高效。

關於 Alamofire

如果你使用過 Objective-C 進行開發,那麼你一定對 AFNetworking 這個庫不陌生,在 Objective-C 生態中,這個庫作爲做常用的網絡操作庫之一,被大家廣泛使用。Mattt Thompson 作爲 AFNetworking 的發起人,在貢獻了這個強大的第三方庫之後,又基於 Swift 語言開發了一個新的網絡操作庫 - Alamofire。而 AFNetworking 前面的 AF 正是 Alamofire 的字頭縮寫。這樣說起來就很明白了吧~

開始行動

現在我們就開始嘗試使用 Alamofire 進行網絡操作。

創建 Playground

首先在一個合適的地方建立一個目錄:

$ mkdir alamofire

目錄創建好之後,我們在這個目錄中創建一個空的 workspace 文件,打開 Xcode 選擇 File -> New -> Workspace...

將新建的 workspace 保存到我們剛剛創建的目錄中。

然後打開這個 workspace ,點擊 File -> New -> Playground... 在這個 workspace 中創建一個新的 Playground,在選項表單中填寫如下內容:

然後點擊下一步,將新創建的 Playground 存儲到我們剛剛創建的目錄中。

安裝 Alamofire

我們推薦使用 Carthage 包管理的方式來安裝 Alamofire,當然你也可以用你喜歡的其他方式來安裝 Alamofire。

Alamofire 的 Github 主頁上面詳細說明了各種安裝方法: https://github.com/Alamofire/Alamofire
我們也有一篇文章介紹如何使用 Carthage 包管理: http://swiftcafe.io/2015/10/25/swift-daily-carthage-package

如果需要,可以參考上面列出的內容。那麼,我們就正式開始了,首先我們在我們創建的 alamofire 目錄中創建一個 Cartfile 文件,裏面寫入 Carthage 包管理的配置信息:

github "Alamofire/Alamofire" ~> 3.0

配置文件裏面非常簡單,僅僅將 Alamofire 的 Github 名稱和版本寫進來。現在我們的 alamofire 目錄應該包含這兩個文件:

Cartfile
alamofire.playground

一個是 Carthage 的配置文件,另一個是我們剛剛創建的 playground 文件。配置完成後,我們輸入:

carthage update

這個命令可以將我們在 Cartfile 中配置的依賴庫下載並且構建出來,構建成功後,我們可以在 Carthage/Build/iOS 目錄中看到構建出來的 Alamofire.framwork 庫:

還可以在 Checkouts 目錄中看到 Alamofire 的原始項目:

我們把 Checkouts 中的 Alamofire 目錄拖動到我們的 workspace 中:

這樣我們的 storyboard 就能夠檢測到 Alamofire 庫了。

開始使用 Alamofire

環境配置好之後,我們可以在 storyboard 中導入 Alamofire 庫:

import Alamofire
發送基本請求

導入完成後,我們就可以使用 Alamofire 請求網絡了,我們可以發送最基本的 GET 請求:

Alamofire.request(.GET, "https://swiftcafe.io")

當然,我們還可以爲請求添加參數,並且處理響應信息,調用方式也很簡單:

Alamofire.request(.GET, "https://httpbin.org/get", parameters: ["foo": "bar"])
    .responseJSON { response in
        
        print(response.request)  // 請求對象
        print(response.response) // 響應對象
        print(response.data)     // 服務端返回的數據
        
        if let JSON = response.result.value {
            print("JSON: \(JSON)")
        }
        
}

Alamofire 提供了多種返回數據的序列化方法,比如剛纔我們用到的 responseJSON, 會返回服務端返回的 JSON 數據,這樣就不用我們自己再去解析了。

下面是 Alamofire 目前支持的數據序列化方法:

  1. response()
  2. responseData()
  3. responseString(encoding: NSStringEncoding)
  4. responseJSON(options: NSJSONReadingOptions)
  5. responsePropertyList(options: NSPropertyListReadOptions)

支持普通數據,字符串, JSON 和 plist 形式的返回。

上傳文件

Alamofire 提供了 upload 方法用於上傳本地文件到服務器:

let fileURL = NSBundle.mainBundle().URLForResource("Default", withExtension: "png")
Alamofire.upload(.POST, "https://httpbin.org/post", file: fileURL)

當然,我們還可以獲取上傳時候的進度:

Alamofire.upload(.POST, "https://httpbin.org/post", file: fileURL)
         .progress { bytesWritten, totalBytesWritten, totalBytesExpectedToWrite in
             print(totalBytesWritten)

             // This closure is NOT called on the main queue for performance
             // reasons. To update your ui, dispatch to the main queue.
             dispatch_async(dispatch_get_main_queue()) {
                 print("Total bytes written on main queue: \(totalBytesWritten)")
             }
         }
         .responseJSON { response in
             debugPrint(response)
         }

還支持 MultipartFormData 形式的表單數據上傳:

Alamofire.upload(
    .POST,
    "https://httpbin.org/post",
    multipartFormData: { multipartFormData in
        multipartFormData.appendBodyPart(fileURL: unicornImageURL, name: "unicorn")
        multipartFormData.appendBodyPart(fileURL: rainbowImageURL, name: "rainbow")
    },
    encodingCompletion: { encodingResult in
        switch encodingResult {
        case .Success(let upload, _, _):
            upload.responseJSON { response in
                debugPrint(response)
            }
        case .Failure(let encodingError):
            print(encodingError)
        }
    }
)
下載文件

Alamofire 同樣也提供了文件下載的方法:

Alamofire.download(.GET, "https://httpbin.org/stream/100") { temporaryURL, response in
    let fileManager = NSFileManager.defaultManager()
    let directoryURL = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
    let pathComponent = response.suggestedFilename

    return directoryURL.URLByAppendingPathComponent(pathComponent!)
}

還可以設置默認的下載存儲位置:

let destination = Alamofire.Request.suggestedDownloadDestination(directory: .DocumentDirectory, domain: .UserDomainMask)
Alamofire.download(.GET, "https://httpbin.org/stream/100", destination: destination)

也提供了 progress 方法檢測下載的進度:

Alamofire.download(.GET, "https://httpbin.org/stream/100", destination: destination)
         .progress { bytesRead, totalBytesRead, totalBytesExpectedToRead in
             print(totalBytesRead)

             dispatch_async(dispatch_get_main_queue()) {
                 print("Total bytes read on main queue: \(totalBytesRead)")
             }
         }
         .response { _, _, _, error in
             if let error = error {
                 print("Failed with error: \(error)")
             } else {
                 print("Downloaded file successfully")
             }
         }
HTTP 驗證

Alamofire 還很提供了一個非常方便的 authenticate 方法提供了 HTTP 驗證:

let user = "user"
let password = "password"

Alamofire.request(.GET, "https://httpbin.org/basic-auth/\(user)/\(password)")
         .authenticate(user: user, password: password)
         .responseJSON { response in
             debugPrint(response)
         }
HTTP 響應狀態信息識別

Alamofire 還提供了 HTTP 響應狀態的判斷識別,通過 validate 方法,對於在我們期望之外的 HTTP 響應狀態信息,Alamofire 會提供報錯信息:

Alamofire.request(.GET, "https://httpbin.org/get", parameters: ["foo": "bar"])
         .validate(statusCode: 200..<300)
         .validate(contentType: ["application/json"])
         .response { response in
             print(response)
         }

validate 方法還提供自動識別機制,我們調用 validate 方法時不傳入任何參數,則會自動認爲 200...299 的狀態嗎爲正常:

Alamofire.request(.GET, "https://httpbin.org/get", parameters: ["foo": "bar"])
         .validate()
         .responseJSON { response in
             switch response.result {
             case .Success:
                 print("Validation Successful")
             case .Failure(let error):
                 print(error)
             }
         }
調試狀態

我們通過使用 debugPrint 函數,可以打印出請求的詳細信息,這樣對我們調試非常的方便:

let request = Alamofire.request(.GET, "https://httpbin.org/get", parameters: ["foo": "bar"])

debugPrint(request)

這樣就會產生如下輸出:

$ curl -i \
    -H "User-Agent: Alamofire" \
    -H "Accept-Encoding: Accept-Encoding: gzip;q=1.0,compress;q=0.5" \
    -H "Accept-Language: en;q=1.0,fr;q=0.9,de;q=0.8,zh-Hans;q=0.7,zh-Hant;q=0.6,ja;q=0.5" \
    "https://httpbin.org/get?foo=bar"

結語

Alamofire 是一個非常強大並且使用簡潔的網絡操作庫,接口非常的簡單,而且穩定。關於 Alamofire 的更多信息,大家還可以到它的 Github 主頁上面瞭解到更多。大家也可以下載我們這裏個 playground 演示示例: https://github.com/swiftcafex/alamofireSamples

更多精彩內容可關注微信公衆號:
swift-cafe

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章