標籤:des style blog http io ar color os 使用
上篇中主要講了介面的一些內容,這篇主要討論網路請求,獲得天氣的資料。具體的說是HTTP請求天氣網站的API,得到返回的JSON資料。解析這些資料,並更新到介面內容中。 讓使用者知道當前的和之後幾個小時的天氣狀況。
發起HTTP請求主要用到的是SDK的NSURLSession這個類,使用這個類對象可以建立請求任務並在這個任務中處理請求之後由伺服器返回的JSON資料。在NSURLSession之前主要用到的是NSURLConnection。這兩個類比較類似。只是在NSURLSession中增加了後台執行的請求。發起網路請求的時候,使用NSURLSession建立對應的NSURLSessionTask,並由這個Task請求伺服器和處理返回的資料。
下面大體的看看我們怎麼做HTTP請求的。本文將主要敘述如何發起HTTP請求。先講講使用最基本的iOS的SDK發請求,然後敘述如何用現在比較流向的AFNetworking架構請求。或許你也聽說過一個叫做ASIHttpRequest的架構,但是這個已經很久沒有人維護了。所以,這裡就不再提及。
使用iOS SDK發起HTTP網路請求:
1. 準備訪問伺服器的NSURL對象。這個對象需要一個url字串,比如百度的地址字串就是“http://www.baidu.com”,我們這裡需要一個指向天氣伺服器的字串。
var weatherUrl = "http://api.openweathermap.org/data/2.5/forecast?lat=\(latitude)&lon=\(longitude)"var url = NSURL(string: weatherUrl)
第一句的問好後面的部分?lat=\(latitude)&lon=\(longitude)是為url指定使用者當前的經緯度。之後根據這個url字串產生NSURL對象。
2. 建立NSURLSession對象。NSURLSession有一個類方法建立執行個體。
self.urlSession = NSURLSession.sharedSession()
一般用到shareXXX的方式命名的方法是一個單例方法。也就是這個方法在被調用的時候會判斷需要的執行個體是否已經建立,如果是的話返回建立好的執行個體,如果沒有建立則初始化一個並儲存起來以備下次使用。關於使用Swift實現單例模式,請參考這裡。
3. 建立NSURLSessionDataTask,並設定好如何處理請求返回的資料。然後開始HTTP請求。
var task = self.urlSession.dataTaskWithURL(url!, completionHandler: {(data:NSData!, response: NSURLResponse!, error: NSError!) in if error != nil { println("http request error \(error)") return } println("\(response)") var httpResponse = response as NSHTTPURLResponse var statusCode: NSInteger = httpResponse.statusCode println("status code: \(statusCode)") var error: NSError? var jsonDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments, error: &error) as NSDictionary if error != nil { println("json error") return } println("json \(jsonDictionary)") self.jsonLabel.text = jsonDictionary.description }) task.resume()
self.urlSession.dataTaskWithURL這個方法建立了一個DataTask。completionHandler後面的就是指定的處理返回資料的方法。這裡使用了Swit的閉包。閉包的文法可以簡單的概括為{(參數列表。。。)->閉包的傳回型別 in 功能代碼在這裡}具體的參考上面的程式碼範例。那麼具體的,我們應該如何處理返回的資料呢。第一步,先查看返回的錯誤error是否為空白。如果為空白就是沒有錯,否則,就是有錯了。這個時候就可以提示使用者後直接return,不再處理後面的代碼了。
下面就是檢查response的statusCode。狀態代碼最直觀的就是大家都見過的404,蝦米都木有找到的時候的提示。如果是200,那麼就是請求伺服器成功。否則,也可以提示使用者後返回了。
最後就是解析使用者資料了。首先需要把伺服器返回的JSON格式的資料轉換為Swift可以直接存取的NSDictionary。記住,這裡是NSDictionary不是Swift基礎資料類型中的泛型Dictionary<KeyType, ValueType>。伺服器的JSON資料轉換成NSDictionary後就可以取出需要的資料並更新到主介面上了。
這裡你會發現很多的代碼調用都是通過NSError的執行個體是否為空白判斷某函數的執行是否有錯誤發生的。Swift沒有try-catch的異常處理模式。只有這樣的error的方式。這個大家需要習慣。用這種方式處理錯誤是為了去掉代碼的二意性。有其他語言編程經理的都知道,有時候就用try-catch來做代碼的某些判斷了。這是不對的。
最後調用task的resume方法開始HTTP請求。
前文已經簡單的提到過定位的功能。本文在這裡之前都在討論HTTP請求的功能。如前面提到的,請求天氣資料到時候需要用到經緯度的資料作為url參數。所以HTTP請求只能在定位成功擷取到使用者當前的經緯度之後進行。所以,在代碼實現的時候,網路請求在Location Manager的定位成功的代理方法中發起。
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!){ println("get location") var location:CLLocation = locations[locations.count-1] as CLLocation if (location.horizontalAccuracy > 0) { self.locationManager.stopUpdatingLocation() println(location.coordinate) self.textLabel.text = "latitude \(location.coordinate.latitude) longitude \(location.coordinate.longitude)" // 在這裡發起HTTP請求 self.updateWeatherWith(location.coordinate.latitude, longitude: location.coordinate.longitude) } }
到此為止,從擷取使用者位置到使用使用者的經緯度資料請求天氣伺服器擷取天氣的JSON資料的功能都已經銜接在一起了。
那麼,我們來討論一下如何使用AFNetworking這個架構(framework)。在這之前,使用者需要配置cocoaPods。具體的步驟可以參考這裡。這裡必須吐槽一下,Ruby什麼的編程之類的網站多要牆真是不可理喻啊。配置好之後,親,你一定要點擊的時候workspace那個尾碼的檔案,不是專案檔了。否則會出錯。
要使用AFNetworking架構就涉及到一個Objective-C和Swift互動的問題了。
let manager = AFHTTPRequestOperationManager()
這行代碼直接編譯不通過。。。稍微深究機會發現,在Swift中沒有辦法直接使用OC(Objective-C)的代碼。翻翻項目,找到SwiftWeather-Bridging-Header.h標頭檔,然後在裡面添加對於AFNetworking架構的引用。
#import <AFNetworking/AFNetworking.h>
添加後,編譯你的項目。上面那行出錯的代碼就可以用了。
使用AFNetworking架構確實會很方便。不用像使用NSURLSession裡那樣寫那麼多的代碼。這個通過一個簡單的感官比較就會得出結論。先在上AFNetworking的HTTP請求代碼。
let manager = AFHTTPRequestOperationManager() let url = "http://api.openweathermap.org/data/2.5/forecast" println(url) let params = ["lat":latitude, "lon":longitude, "cnt":0] println(params) manager.GET(url, parameters: params, success: { (operation: AFHTTPRequestOperation!, responseObject: AnyObject!) in //println("JSON: " + responseObject.description!) self.updateUISuccess(responseObject as NSDictionary!) }, failure: { (operation: AFHTTPRequestOperation!, error: NSError!) in println("Error: " + error.localizedDescription) self.loading.text = "Internet appears down!" })
初始化一個AFHTTPRequestOperationManager來處理請求和資料返回等的處理,一個類就夠了。不用task什麼的了。指定要訪問的url字串,這裡是字串也不需要NSURL的執行個體了。然後把需要給url字串添加的參數放在一個Dictionary<String, String>泛型字典中。然後用manager發出HTTP請求,並指定了請求的方式為GET,函數的名字就是HTTP請求的方式。HTTP請求還有除GET之外的很多中,其中最常用的是POST。然後可以看到GET方法中的sucess和failure,都分別是在指定請求成功的處理代碼和失敗的處理代碼。
用Swift實現一款天氣預報APP(二)