mvvm设计模式之前在oc中有讲过,现在就不在介绍了。
现在用swift语法直接上代码。
首先看下架构情况,model-View-viewModel-controller。
- model:->GameModel
import UIKit
class GameModel: NSObject,NSCoding {
var cname: String = ""
var ename: String = ""
var img: String = ""
var ext: String = ""
var status: Int?
var cdn_rate: Int?
init(dict: [String: Any]) {
super.init()
setValuesForKeys(dict)
}
override func setValue(_ value: Any?, forUndefinedKey key: String) {}
// MARK:- 处理需要归档的字段
func encode(with aCoder:NSCoder) {
aCoder.encode(cname, forKey:"cname")
aCoder.encode(ename, forKey:"ename")
aCoder.encode(img, forKey:"img")
aCoder.encode(ext, forKey:"ext")
aCoder.encode(status, forKey:"status")
aCoder.encode(cdn_rate, forKey:"cdn_rate")
}
// MARK:- 处理需要解档的字段
required init(coder aDecoder:NSCoder) {
super.init()
cname = (aDecoder.decodeObject(forKey:"cname")as? String)!
ename = (aDecoder.decodeObject(forKey:"ename")as? String)!
img = (aDecoder.decodeObject(forKey:"img")as? String)!
ext = (aDecoder.decodeObject(forKey:"ext")as? String)!
status = aDecoder.decodeObject(forKey:"status")as? Int
cdn_rate = aDecoder.decodeObject(forKey:"cdn_rate")as? Int
}
override init() {
super.init()
}
}
-
view->CollectionGameCell.swift
import UIKit class CollectionGameCell: UICollectionViewCell { @IBOutlet weak var imageView: UIImageView! @IBOutlet weak var nameLabel: UILabel! var gameModel: GameModel? { didSet { guard let iconURL = URL(string: gameModel?.img ?? "") else { return } imageView.kf.setImage(with: iconURL) nameLabel.text = gameModel?.cname } } }
---> CollectionGameCell.xib
-
viewModel->GameVM
一般来说,在创建viewmodel时会先给一个基础的baseViewModel,与网络请求连用.这里的数据类型简单,就直接用GameVM了。
import UIKit
class GameVM: NSObject {
lazy var gameArray: [GameModel] = GameModelfunc loadGameData(finishedCallback : @escaping () -> ()) { NetworkTool.request(type: .GET, urlString: "http://api.m.panda.tv/index.php", paramters: ["method":"category.list", "type":"game", "__version":"1.1.7.1305", "__plat":"ios", "__channel":"appstore"]) { (result) in guard let resultDict = result as? [String: NSObject] else { return } guard let dataArray = resultDict["data"] as? [[String: NSObject]] else { return } for dict in dataArray { self.gameArray.append(GameModel(dict: dict)) } finishedCallback() } } }
当然除了这些还需要有网络请求模块.
这里我是用pod导入第三方框架。pod 'Alamofire'
封装了一个网络请求的类
NetworkTool.swift
import UIKit
import Alamofire
enum MethodType {
case GET
case POST
}
class NetworkTool {
class func request(type: MethodType, urlString: String, paramters: [String: Any]? = nil, finishedCallback: @escaping (_ result: Any) -> ()) {
// 获取类型
let method = type == .GET ? HTTPMethod.get : HTTPMethod.post
// 发送网络请求
Alamofire.request(urlString, method: method, parameters: paramters).responseJSON { (response) in
guard let result = response.result.value else {
print(response.result.error)
return
}
// 回调
finishedCallback(result as AnyObject)
}
}
}
-
controller ->GameVC.swift
import UIKit private let kGameItemMargin : CGFloat = 4 private let kItemW = (kScreenW - kGameItemMargin * 4) / 3 private let kItemH = kScreenW / 2 private let kGameCellID = "kGameCellID" class GameVC: UIViewController { fileprivate lazy var gameArray = [GameModel]() fileprivate lazy var gameVM:GameVM = { let model = GameVM() return model }() //懒加载属性 fileprivate lazy var collectionView:UICollectionView = { [unowned self] in let layout = UICollectionViewFlowLayout() layout.itemSize = CGSize(width: kItemW, height:kItemH) layout.minimumLineSpacing = kGameItemMargin layout.minimumInteritemSpacing = kGameItemMargin layout.sectionInset = UIEdgeInsets(top: kGameItemMargin, left:kGameItemMargin,bottom:kGameItemMargin,right:kGameItemMargin) let collectionView = UICollectionView(frame:self.view.bounds,collectionViewLayout:layout) collectionView.backgroundColor = BGCOLOR collectionView.dataSource = self collectionView.delegate = self collectionView.autoresizingMask = [.flexibleHeight, .flexibleWidth] collectionView.register(UINib(nibName: "CollectionGameCell", bundle: nil), forCellWithReuseIdentifier: kGameCellID) return collectionView }() override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = UIColor.white self.title = "游戏" setupUI() requestData() } } //遵循协议(用扩展方式分类出来) extension GameVC: UICollectionViewDataSource,UICollectionViewDelegate { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return gameVM.gameArray.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: kGameCellID, for: indexPath) as! CollectionGameCell cell.backgroundColor = UIColor.white cell.gameModel = gameVM.gameArray[indexPath.item] return cell } func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { //点击cell 跳转控制器 let moreVC = MoreLivingVC() let model = gameVM.gameArray[indexPath.item] moreVC.cateName = model.ename moreVC.title = model.cname self.navigationController?.pushViewController(moreVC, animated: true) } }
//创建UI和请求数据
extension GameVC {//MARK 设置UI
fileprivate func setupUI() {view.addSubview(collectionView)
}
//MARK 发送网络请求
fileprivate func requestData() {//mvc模式请求数据成功
// NetworkTool.request(type: .GET, urlString: "http://api.m.panda.tv/index.php", paramters: ["method":"category.list", "type":"game", "__version":"1.1.7.1305", "__plat":"ios", "__channel":"appstore"]) { (result) in
// guard let resultDict = result as? [String: NSObject] else { return }
// guard let dataArray = resultDict["data"] as? [[String: NSObject]] else { return }
// for dict in dataArray {
// self.gameArray.append(GameModel(dict: dict))
// }
// self.collectionView.reloadData()
// }//mvvm模式,回调刷新成功 gameVM.loadGameData() { self.collectionView.reloadData() }
}
}
运行结果如图: