渋谷で引きこもってる社長です

株式会社Chotchy代表取締役 / エンジニア

SwiftBondを使ってiOSでシンプルなリアクティブプログラミングを試す![TableView編]

弊社の学生iOSエンジニアのおーつか君がSwiftBondのサンプルコードを作ってくれたのでそれからちょいちょいSwiftBondを触ってるのですが、とてもいいですねこれ。Delegateを自分で作るなんてことも無くなりそうです。

何がいいかって完全にViewとControllerを切り離せるところにあると思いますね。

そんなSwiftBondでのReactive ProgrammingをUITableViewで試したサンプルコードを載せたいともいます。SwiftBondでもdidSelectなどのDelegateが使えるので見てみてください。

試しにTableViewではどうなってるのかを説明したいと思います。

ちなみにおーつか君のサンプルコードはこちらです!

github.com

 

Model

まずはDataの型を決めます。Webからデータを取得する前提になっています。

Data.swift 
import Foundation 
import SwiftyJSON 
import RealmSwift 
struct Data { 
  let thumbNail: String 
  let titleText: String 
  
  init(json: JSON) { 
    self.thumbNail = json["thumbnail"].stringValue 
    self.titleText = json["title"].stringValue 
  } 
}

次に、ViewModelです。ここで、Viewに渡す最終的な形まで持って行きます。


import Foundation 
import RealmSwift 
import UIKit 
import Bond 
class DataViewModel{ 
  ///このデータを監視対象にします。 
  internal var data = ObservableArray()
  
  //シングルトンパターン 
  static var sharedInstance: DataViewModel = { 
    return DataViewModel() 
  }() 
  private init() { } 
  
  //データの中身の更新処理 
  func update(){ 
    data.removeAll() 
    Alamofire.request(.GET, "https://hogeghoge.jp", parameters: ["category_id": category_id]) .responseJSON { response in 
      if response.result.isSuccess{
        let j = JSON(response.result.value!) 
        for i in 0..<j["list"].count { 
          let data = VideoData(json: j["list"][i]) 
          self.data.append(data) 
        } 
      } 
    } 
  } 
}

ViewController


import Foundation
import UIKit
import PopupController
import Bond

class DataViewController: UIViewController{
    
    var tableView: UITableView!
    //監視対象
    private var data = ObservableArray<ObservableArray>()
    private let dataModel = DataViewModel.sharedInstance
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.like = [likeModel.like]
        DataViewModel.sharedInstance.update()
        
        tableView = UITableView(frame: self.view.frame)
        tableView.registerClass(DataViewCell.self, forCellReuseIdentifier: "ViewCell")
        tableView.rowHeight = 86
        tableView.delegate = self
        self.view.addSubview(tableView)
        
        //データのバインディング
        data.bindTo(tableView) { indexPath, dataSources, tableView in
            let cell = tableView.dequeueReusableCellWithIdentifier("ViewCell", forIndexPath: indexPath) as! DataViewCell
            let dataSource = dataSources[indexPath.section][indexPath.row]
            cell.data = dataSource
            return cell
        }
    }

}

//選択時のDelegateはextensionで対応。
extension LikeViewController: UITableViewDelegate{
    
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        print(indexPath.section)
    }
}
    

View

TableViewCellにバインドするところです。


import Foundation
import SDWebImage
import UIKit

class DataViewCell: UITableViewCell {
    

    var thumbNail: UIImageView!
    var title: UILabel!
    
    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
    }
    
    //データのバインドはdataのdidSetで行う
    var data: Data? {
        didSet{
            //nilチェック
            guard let data = self.data else { return }
            self.title.text = data.titleText
            self.thumbNail.sd_setImageWithURL(NSURL(string: data.thumbNail))
        }
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
}
    

こんな感じです!もっと詳しく聞きたい人はinfo[@]chotchy.comまで!