娱乐基本展示
效果展示
- 如图
!
内容的展示
界面布局
-
内容的展示依然是一个UICollectionView
- 懒加载UICollectionView
- 将UICollectionView添加到控制器的View中
- 实现数据源&代理
-
懒加载UICollectionView
private let kItemMargin : CGFloat = 10private let kItemW = (kScreenW - 3 * kItemMargin) / 2private let kNormalItemH = kItemW * 3 / 4private let kPrettyItemH = kItemW * 4 / 3private let kHeaderViewH : CGFloat = 50private let kNormalCellID = "kNormalCellID"private let kPrettyCellID = "kPrettyCellID"private let kHeaderViewID = "kHeaderViewID"class AmuseViewController: UIViewController {// MARK: 懒加载属性fileprivate lazy var collectionView : UICollectionView = {[unowned self] in// 1.创建布局let layout = UICollectionViewFlowLayout()layout.itemSize = CGSize(width: kItemW, height: kNormalItemH)layout.minimumLineSpacing = 0layout.minimumInteritemSpacing = kItemMarginlayout.headerReferenceSize = CGSize(width: kScreenW, height: kHeaderViewH)layout.sectionInset = UIEdgeInsets(top: 0, left: kItemMargin, bottom: 0, right: kItemMargin)// 2.创建UICollectionViewlet collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: layout)collectionView.backgroundColor = UIColor.whitecollectionView.dataSource = selfcollectionView.delegate = selfcollectionView.autoresizingMask = [.flexibleHeight, .flexibleWidth]collectionView.register(UINib(nibName: "CollectionNormalCell", bundle: nil), forCellWithReuseIdentifier: kNormalCellID)collectionView.register(UINib(nibName: "CollectionPrettyCell", bundle: nil), forCellWithReuseIdentifier: kPrettyCellID)collectionView.register(UINib(nibName: "CollectionHeaderView", bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: kHeaderViewID)return collectionView}()// MARK: 系统回调override func viewDidLoad() {super.viewDidLoad()setupUI()}}
- 实现数据源&代理方法
// MARK:- 遵守UICollectionView的数据源&代理协议extension AmuseViewController : UICollectionViewDataSource, UICollectionViewDelegate {func numberOfSections(in collectionView: UICollectionView) -> Int {return 8}func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {return 4}func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {// 1.获取Celllet cell = collectionView.dequeueReusableCell(withReuseIdentifier: kNormalCellID, for: indexPath)cell.backgroundColor = UIColor.randomColor()return cell}}
请求数据&展示数据
- 接口描述
- 请求地址:http://capi.douyucdn.cn/api/v1/getHotRoom/2
- 请求参数:无参数
- ViewModel封装
class AmuseViewModel {fileprivate lazy var anchorGroups : [AnchorGroup] = [AnchorGroup]()}extension AmuseViewModel {func loadAmuseData(finishedCallback : @escaping () -> ()) {NetworkTools.requestData(.get, URLString: "http://capi.douyucdn.cn/api/v1/getHotRoom/2") { (result) in// 1.获取数据guard let resultDict = result as? [String : Any] else { return }guard let dataArray = resultDict["data"] as? [[String : Any]] else { return }// 2.字典转模型for dict in dataArray {self.anchorGroups.append(AnchorGroup(dict: dict))}// 3.回调数据finishedCallback()}}}
- 控制器中展示数据
- 修改之前的数据源&代理
fileprivate func loadData() {amuseVM.loadAmuseData {self.collectionView.reloadData()}}
父类抽取
- 展示内容,我们会发现,该界面和推荐界面相似度非常非常高
- 相似:添加UICollectionView,并且每组有对应的HeaderView
- 不同:推荐界面第1组使用的是PrettyCell
- 思考:
- 既然相似度很高,那么我们可以抽取父类
- 将相同代码抽取到父类中,不同代码子类自己来实现
- 请求数据的ViewModel的抽取
class BaseViewModel {lazy var anchorGroups : [AnchorGroup] = [AnchorGroup]()}extension BaseViewModel {func loadAnchorData(URLString : String, parameters : [String : Any]? = nil, finishedCallback : @escaping () -> ()) {NetworkTools.requestData(.get, URLString: URLString, parameters: parameters) { (result) in// 1.获取数据guard let resultDict = result as? [String : Any] else { return }guard let dataArray = resultDict["data"] as? [[String : Any]] else { return }// 2.字典转模型for dict in dataArray {self.anchorGroups.append(AnchorGroup(dict: dict))}// 3.回调数据finishedCallback()}}}
- 抽取懒加载UICollectionView
- 两个控制器都需要懒加载一个UICollectionView
- 并且UICollectionView需要设置的内容和尺寸也是一致的
- 实现数据源&代理
- 无论是推荐还是娱乐都需要成为UICollectionView的数据源&代理
- 如果子类有不同的实现,可以让子类自己实现
private let kItemMargin : CGFloat = 10private let kHeaderViewH : CGFloat = 50let kItemW = (kScreenW - 3 * kItemMargin) / 2let kNormalItemH = kItemW * 3 / 4let kPrettyItemH = kItemW * 4 / 3private let kNormalCellID = "kNormalCellID"private let kHeaderViewID = "kHeaderViewID"let kPrettyCellID = "kPrettyCellID"class BaseAnchorViewController: UIViewController {// MARK: 懒加载属性var baseVM : BaseViewModel!lazy var collectionView : UICollectionView = {[unowned self] in// 1.创建布局let layout = UICollectionViewFlowLayout()layout.itemSize = CGSize(width: kItemW, height: kNormalItemH)layout.minimumLineSpacing = 0layout.minimumInteritemSpacing = kItemMarginlayout.headerReferenceSize = CGSize(width: kScreenW, height: kHeaderViewH)layout.sectionInset = UIEdgeInsets(top: 0, left: kItemMargin, bottom: 0, right: kItemMargin)// 2.创建UICollectionViewlet collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: layout)collectionView.backgroundColor = UIColor.whitecollectionView.dataSource = selfcollectionView.delegate = selfcollectionView.autoresizingMask = [.flexibleHeight, .flexibleWidth]collectionView.register(UINib(nibName: "CollectionNormalCell", bundle: nil), forCellWithReuseIdentifier: kNormalCellID)collectionView.register(UINib(nibName: "CollectionPrettyCell", bundle: nil), forCellWithReuseIdentifier: kPrettyCellID)collectionView.register(UINib(nibName: "CollectionHeaderView", bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: kHeaderViewID)return collectionView}()// MARK: 系统回调override func viewDidLoad() {super.viewDidLoad()setupUI()loadData()}}// MARK:- 设置UI界面内容extension BaseAnchorViewController {func setupUI() {view.addSubview(collectionView)}func loadData() {}}// MARK:- 遵守UICollectionView的数据源&代理协议extension BaseAnchorViewController : UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {func numberOfSections(in collectionView: UICollectionView) -> Int {return baseVM.anchorGroups.count}func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {return baseVM.anchorGroups[section].anchors.count}func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {// 1.获取Celllet cell = collectionView.dequeueReusableCell(withReuseIdentifier: kNormalCellID, for: indexPath) as! CollectionNormalCellcell.anchor = baseVM.anchorGroups[indexPath.section].anchors[indexPath.item]return cell}func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {// 1.取出headerViewlet headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: kHeaderViewID, for: indexPath) as! CollectionHeaderViewheaderView.group = baseVM.anchorGroups[indexPath.section]return headerView}func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {return CGSize(width: kItemW, height: kNormalItemH)}}
- 让RecommendViewController&AmuseViewController集成子BaseAnchorViewController
- 修改对应的代码即可
本文介绍了一个UICollectionView懒加载的实现方案,包括UICollectionView的设置、数据源和代理方法的实现,以及如何通过ViewModel封装请求数据并展示。
8446

被折叠的 条评论
为什么被折叠?



