読者です 読者をやめる 読者になる 読者になる

【swift】kvoパターンを使うためにmodelクラスをつくる

はじめに

今回やりたかったのはapiからデータを取得
そのデータをアプリ内で使いまわしつつデータの更新があればapiも叩いてサーバサイドにも反映

ちょっとわかりずらいけどやりたいことはこんな感じです

作りたい画面

一覧画面

apiからデータを取得してテーブルビューに表示

詳細画面

・一覧画面で選択されたデータの詳細情報を表示
・データの編集などもこの画面で行える

で、1番やりたかったのはデータの編集などを行った際に一覧画面にも反映されているということでした

実装(Model)

ModelBase.swift(Modelのベースクラス)

class ModelBase: NSObject {
    
    dynamic var list: [Dictionary<String,AnyObject>] = [Dictionary<String,AnyObject>]()
    
    func get(row: Int) -> Dictionary<String,AnyObject> {
        return self.list[row]
    }
    
    func set(row: Int, data: Dictionary<String,AnyObject>) {
        self.list[row] = data
    }
    
    func getAll() -> [Dictionary<String,AnyObject>] {
        return self.list
    }
    
    func remove(row: Int) {
        self.list.removeAtIndex(row)
    }
    
    func add(data: Dictionary<String,AnyObject>) {
        self.list.insert(data, atIndex: self.list.count)
    }
}

ModelNote.swift

class ModelNotes : ModelBase {

    class var sharedInstance : ModelNotes {
        struct Singleton {
            static var instance = ModelNotes()
        }
        return Singleton.instance
    }
    
    func getList(params: Dictionary<String,AnyObject>?) {
        Alamofire.manager
            .request(.POST, "http://example.com/path/to", parameters: params)
            .responseJSON { request, response, JSON, error in
                var response =  Dictionary<String,AnyObject>()
                if var parse = JSON as? Dictionary<String,AnyObject> {
                    response = parse
                }
                if var list = response["data"] as? [Dictionary<String,AnyObject>] {
                    for var i = 0; i < list.count; i++ {
                        self.add(list[i])
                    }
                }
        }
    }
}

実装(コントローラー)

ListViewController.swift

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    var tableView: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // ModelNotes.listの変更を監視
        ModelNotes.sharedInstance.addObserver(self, forKeyPath: "list", options: .New, context: nil)

        // 一覧取得
        ModelNotes.sharedInstance.getList(Dictionary<String,AnyObject>())
        
        // VIEWをセットします
        setView()
    }
    
    // ModelNotes.listを監視 変更があったら再描画
    override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<Void>) {
        tableView.reloadData()
    }
    
    // テーブルの行数をかえします
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        var list = ModelNotes.sharedInstance.getAll()
        return list.count
    }
    
    // テーブルセルにデータをセットします
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
        cell.selectionStyle = UITableViewCellSelectionStyle.None
        var data = ModelNotes.sharedInstance.get(indexPath.row)
        cell.textLabel?.text = data["name"] as? String
        return cell
    }
    
    // テーブルセル選択時の処理を記述します
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        var viewController: DetailViewController = DetailViewController()
        viewController.row = indexPath.row
        self.navigationController?.pushViewController(viewController, animated: true)
    }
}

DetailViewController.swift

class DetailViewController: UIViewController {
    
    var row: Int!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = UIColor.whiteColor()
        
        // VIEWをセットします
        setView()
    }
    
    func setView() {
        
        // データを取得
        var data = ModelNotes.sharedInstance.get(row)
        
        var label: UILabel = UILabel(frame: CGRectMake(0, 100, self.view.frame.width, 50))
        label.textAlignment = NSTextAlignment.Center
        label.text = data["name"] as? String
        self.view.addSubview(label)

        // データを更新するとListViewControllerの監視が動く
        // data["name"] = "名前を変更"
        // ModelNotes.sharedInstance.set(row, data)
    }
}

こんな感じでいちおうやりたいことはできました

以上です