使用lazy var声明UICollectionView注册Cell类时为何报错?
我来帮你解决这个问题!你遇到的这个错误看起来有点迷惑——毕竟你的PreviewFilmsPosterCell明明确实继承自UICollectionViewCell对吧?问题其实出在lazy闭包的执行时机和ViewController初始化顺序上。
当你用lazy var闭包创建collection时,这个闭包会在collection第一次被访问时执行,而此时你的ViewController实例还没有完全完成初始化流程。在这个阶段尝试注册Cell类,会导致Swift无法正确识别PreviewFilmsPosterCell的类继承关系,从而抛出那个看似矛盾的错误。而在viewDidLoad中执行注册就没问题,因为此时ViewController已经完全初始化完成,所有类的元信息都能被正确解析。
下面是两种可行的解决方案:
方案一:将Cell注册移到viewDidLoad中(推荐)
保持collection的lazy声明,但把注册Cell的代码从闭包里抽出来,放到viewDidLoad里执行。这样既保留了lazy加载的优势,又避开了初始化阶段的类识别问题,代码结构也更符合iOS开发的常规习惯:
lazy var flowLayout: UICollectionViewFlowLayout = { let f = UICollectionViewFlowLayout() f.scrollDirection = .horizontal f.itemSize = CGSize(width: 100, height: 100) f.minimumInteritemSpacing = CGFloat.greatestFiniteMagnitude f.minimumLineSpacing = 5 return f }() lazy var collection: UICollectionView = { let cv = UICollectionView(frame: CGRect.zero, collectionViewLayout: self.flowLayout) cv.translatesAutoresizingMaskIntoConstraints = false cv.showsVerticalScrollIndicator = false cv.showsHorizontalScrollIndicator = false cv.dataSource = self cv.delegate = self cv.backgroundColor = .black // 移除闭包内的注册代码 return cv }() override func viewDidLoad() { super.viewDidLoad() // 在这里完成Cell注册 collection.register(PreviewFilmsPosterCell.self, forCellWithReuseIdentifier: cellId) // 其他视图初始化代码... }
方案二:调整lazy闭包的捕获列表
另一种方法是在lazy闭包中使用捕获列表,明确指定对self的引用方式,帮助Swift正确处理初始化阶段的类访问:
lazy var collection: UICollectionView = { [unowned self] in let cv = UICollectionView(frame: CGRect.zero, collectionViewLayout: self.flowLayout) cv.translatesAutoresizingMaskIntoConstraints = false cv.showsVerticalScrollIndicator = false cv.showsHorizontalScrollIndicator = false cv.dataSource = self cv.delegate = self cv.register(PreviewFilmsPosterCell.self, forCellWithReuseIdentifier: cellId) cv.backgroundColor = .black return cv }()
两种方案都能解决问题,但方案一的代码可读性和维护性更好,更推荐使用。
内容的提问来源于stack exchange,提问作者Hattori Hanzō
相关产品推荐
相关产品推荐

