UICollectionView基础进阶(一)+ 更轻量的Controller

前言

本文介绍了UICollectionView的用法的扩展,不涉及基础的用法,是我对UICollectionView用法的总结和实战,通过这篇文章,读者可以了解到使用自定义的UICollectionViewDataSouce来使UIViewController更加轻量,使用Model来使UIViewController更加轻量,在下篇文章中,我会继续介绍UICollectionViewLayout的扩展,并且使用UICollectionViewLayout做出一些酷炫的动画,如文章中有错误,欢迎大家指出。

文章参考于:Objc.IO,王巍的博客


UICollectionView简介

  • UICollectionView可以说是和UITableView的扩展,取掉UICollectionViewLayout可以说和UITableView没有太多区别,但当使用Layout时,CollectionView就展示出了自己的高灵活性,可以实现一下非常复杂的布局。

基本的UICollectionView设定

让我们先做点热身,设置一些基本的设定

  • 初始化一个UICollectionView,一定要在初始化时就将layout属性定义在初始化中,不然程序会崩溃,然后让其ConformdelegatedataSource,并注册一个Cell。
  • 这一篇不介绍UICollectionViewLayout的自定义,所以先使用系统提供的UICollectionViewFlowLayout来进行初始化,UICollectionViewFlowLayout是系统提供的流式布局,Cell按顺序排开,一行里的Cell有位置则会在同一行,没有位置的Cell会排在下一行,UICollectionViewFlowLayout的设定可以通过属性,也可以符合UICollectionViewDelegateFlowLayout来设定,详情可见文档。
    private var layout = UICollectionViewFlowLayout()
    
    private lazy var collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: layout)

    override func viewDidLoad() {
        super.viewDidLoad()
                
        collectionView.register(LNCollectionViewCell.self, forCellWithReuseIdentifier: "LNCollectionViewCell")
        
        collectionView.delegate = self
        collectionView.dataSource = self
        
        self.view.addSubview(collectionView)
    }

UICollectionViewDataSource

  • UICollectionViewDataSouce的基本设定如下,返回一个Cell的数量,并设定Cell的样式和使Cell能够复用,到现在为止基本设定已经完成。
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return self.items.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "LNCollectionViewCell", for: indexPath) as! LNCollectionViewCell
        let item = self.items[indexPath.item]
        cell.titleLabel.text = item.text
        
        return cell
    }

更轻量的ViewController

UICollectionViewDataSource往往在Controller里拥有着大量篇幅,多到几十行,甚至上百行,那如何在这方面使Controller更加轻量呢,也许你会说使用extension,使用extension是一个不错的办法,可以使Controller更加清晰,但并没有做到轻量,因为代码还是在这里,Controller依然不堪重负

  • 自定义DataSource并将业务逻辑转移至DataSorce的类里,定义一个Block,使用Block为来设置Cell
	var ConfigureCellBlock: ((_ cell: LNCollectionViewCell, _ indexPath: IndexPath, _ item: LNToDoItem) -> Void)?

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return items.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "LNCollectionViewCell", for: indexPath) as! LNCollectionViewCell
        let item = self.items[indexPath.item]
        if let setUpCellBlock = ConfigureCellBlock {
            setUpCellBlock(cell, indexPath, item)
        }
        
        return cell
    }

现在可以把ViewController中的代码取掉了

  • 简单的使用几行,就可以了
    private var dataSource = LNCollectionViewDataSource()

	collectionView.dataSource = dataSource
        
    dataSource.ConfigureCellBlock = { cell, indexPath, item in
    	let text = item.title
        cell.titleLabel.text = text
    }

随着业务逻辑增加,DataSource的类减轻的负担就越明显

让Model做自己该做的事

  • 为Model定义储存类,使Model做自己的事,而使代码从ViewController中分离出来,ViewController只负责处理协调Model和View,MVC之间应该使用单向流程,当Model发生变化,应该间接向Controller汇报。
class LNStore {
    static var shared = LNStore()
    
    private(set) var items = [LNToDoItem]()
    
    var count: Int { items.count }
    
    var indices: Range<Int> { items.indices }
    
    init() {  }
    
    func append(item: LNToDoItem) {
        items.append(item)
    }
    
    func remove(item: LNToDoItem) {
        guard let index = items.firstIndex(of: item) else { return }
        items.remove(at: index)
    }
    
    func remove(at index: Int) {
        items.remove(at: index)
    }
    
    func edit(origin: LNToDoItem, new: LNToDoItem) {
        guard let index = items.firstIndex(of: origin) else { return }
        items[index] = new
    }
}

将View转移到View层

  • View的定义转移到自己的类里,而不是在viewDidLoad()中设置,该方法只用来设定一些View在自己的类中无法单独实现的设置

总结

这一篇写了UICollectionView的基础实现以及UIViewController的轻量级的优化,下一篇会更加深入的讲解关于UICollectionViewLayout的自定义。

发布了4 篇原创文章 · 获赞 1 · 访问量 110

猜你喜欢

转载自blog.csdn.net/weixin_41473928/article/details/104207323