[Swift-d27] - 實戰開發 - TODOList - API 2 讀取清單資料
(某一天把兩天份的 commit 在一起了忘了開 branch 了…)
接下來就要來寫 api utility 了
我們先開一個 swift 檔案 RestApi.swift
import Foundation
class RestApi {
	var API_key = "55665566"
	var getListUrl = NSURL(string: "http://192.168.1.158:3000/user/kerkerj/todos")
}
先做好前置設定,因為 API 有上簡單的小鎖,因此要先寫起來
還有 request 的網址
以下是 get list 的範例:
func getTodoList(completionHandler: ((NSArray!, NSError!) -> Void)!) {
        var session = NSURLSession.sharedSession()
        
        var request = NSMutableURLRequest(URL: self.getListUrl!)
        request.HTTPMethod = "GET"
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.addValue(self.API_key, forHTTPHeaderField: "API-Key")
        
        let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
            if (error != nil) {
                return completionHandler(nil, error)
            }
            
            var error: NSError?
            let json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &error) as NSArray
            
            if (error != nil) {
                return completionHandler(nil, error)
            } else {
                return completionHandler(json, nil)
            }
        })
        
        task.resume()
    }
我們使用內建的 NSURLSession.sharedSession 以及 NSMutableURLRequest 來建立 request
裡面就是設定一些 header 以及 API-Key
另外在資料回來後,return callback
在這邊有 async,寫隔壁棚的 api 回過頭來看這個感覺很熟悉 XD
設定好 API 後
回到顯示 todo 清單的主頁程式碼
由於我們希望能夠在 view 每次被呼叫時,都可以對 API server 做存取
因此必須要將 getTodoList 寫在該方法裏
該方法為 override func viewWillAppear(animated: Bool) {}
先建立一個 api 物件
var api: RestApi = RestApi()
將原本的假資料刪除或註解, 不過資料物件名稱就繼續用 fakeData XD
//        fakeData = [
//            ["id": "1", "content": "A"],
//            ["id": "2", "content": "B"],
//            ["id": "3", "content": "C"],
//        ]
接著在 ViewController override 一個 viewWillAppear 的方法
override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(true)
        
        api.getTodoList({data, error -> Void in
            if error != nil {
                dispatch_async(dispatch_get_main_queue(), {
                    let alert = UIAlertView()
                    alert.title = "Yoooooooooooooooo"
                    alert.message = "Get list faild, maybe check your network: \(error)"
                    alert.addButtonWithTitle("ok")
                    alert.delegate = self
                    alert.show()
                    println(error)
                })
            }
            
            if (data != nil) {
                
                var tmpArr = [[String: String]]()
                
                for item in data {
                    var _id = item["_id"] as String
                    var content = item["content"] as String
                    var dic = [String: String]()
                    
                    dic["_id"] = _id
                    dic["content"] = content
                    
                    tmpArr.append(dic)
                }
                self.arr = tmpArr
                
                println(self.arr)
                
                dispatch_async(dispatch_get_main_queue(), {
                    // must be "tableView!" not "tableView?"
                    self.tableView!.reloadData()
                })
                
            }
        })
        
        dispatch_async(dispatch_get_main_queue(), {
            // must be "tableView!" not "tableView?"
            self.tableView!.reloadData()
        })
    }
以上方法都是 async 的方式
只要網路錯誤,就會直接跳一個 alert
若有資料的話就 parse
一併轉換成原本定義的 [[String: String]] 中
執行看看吧!
很明顯每次切回主頁時 api console 都會跳一行 request~
如果使用 sync 的方式就會卡很久! 而且更新 UI 還會 crash XD
我覺得這部分是需要好好去做處理的,在這邊的程式碼只是簡單 demo
並沒有考慮到太多 :P
明天繼續!