Github link

(某一天把兩天份的 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

明天繼續!