網絡處理,應該是我們平時開發的時候最常用到的操作。比如讀取 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 目前支持的數據序列化方法:
- response()
- responseData()
- responseString(encoding: NSStringEncoding)
- responseJSON(options: NSJSONReadingOptions)
- 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