Swift 避免重复创建视图的管理适配器

464 阅读1分钟

背景:

有些时候我们总需要根据数据创建一些视图,当刷新了数据又得移除掉重新创建,这样是不是有些浪费资源了。

那么我们来构想下:

能不能实现像 UITableView 中的 Cell 可以重复利用,但是UITableView 的书写是否啰嗦了点。那我们能不能简化些,如像:


// 1. 懒加载创建一个视图管理适配器
lazy var pinAdapter = EPReusableViewAdapter()


// 2. 移除所有可见视图,再在需要的时候按需创建和显示可用视图
pinAdapter.removeAllVisibleViews()

// 拼团用户头像
if let pinUsers = model.spellDetail?.users {
    for (index, user) in pinUsers.enumerated() {
        // 3. pinAdapter 就是一个重用视图的管理适配器,按需创建视图,存在就取出来重用
        let userImgV = pinAdapter.dequeueReusableView { () -> (UIImageView) in
            // 4. 这里的代码只在没有存在可重用的视图才会执行
            let userImgV = UIImageView().then {
                $0.backgroundColor = .muColor(.background)
                $0.layer.cornerRadius = FMPt(15)
                $0.layer.masksToBounds = true
            }
            return userImgV
        }
        self.addSubview(userImgV)
        userImgV.bc_setImageURLString(user.userHead)
        userImgV.snp.makeConstraints {
            $0.width.height.equalTo(FMPt(30))
            $0.centerY.equalTo(titleLab)
            $0.left.equalTo(detailLab.snp.right).offset(FMPt(10)+FMPt(24)*CGFloat(index))
        }

    }

}

这样看起来是不是晴朗些,还是按照正常的代码编写逻辑,只不过往代码中加入了视图管理适配器,让逻辑更加清晰,里面的是怎么管理的就不归我们这业务层的管理了。岂不乐哉!

接下来就看看主代码的实现吧
class EPReusableViewAdapter: NSObject {
    private var reusableViews = [UIView]() // 重用队列
    public var visibleViews = [UIView]() // 可见队列

    /// 获取重用队列中的对象,没有就在block中创建
    public func dequeueReusableView<T: UIView>(_ registerViewBlock: (()->(T))) -> T {
        guard let view = reusableViews.first else {
            // 交给外面来创建
            let newView = registerViewBlock()
            visibleViews.append(newView)
            return newView
        }
        // 已经去除的要从重用队列中移除
        reusableViews.removeFirst()
        visibleViews.append(view)
        return view as! T
    } 

    /// 移除所有可见视图,重新布局
    public func removeAllVisibleViews() {
        for view in visibleViews {
            reusableViews.append(view)
            view.removeFromSuperview()
        }
        visibleViews.removeAll()
    }
}