跨类调用函数时Collection View为nil引发崩溃,求排查解决
问题出在你创建ViewController实例的方式!
你现在调用ViewController().displayCircle()的时候,是新建了一个完全独立的ViewController对象——这可不是你页面上已经显示、加载好视图的那个实例!这个新创建的ViewController根本没被加到视图层级里,它的collectionView自然是nil,你强行用collectionView!解包,直接就触发崩溃了。
而你能看到页面上的collectionView,那是另一个被Page View Controller管理、已经完成视图加载的ViewController实例,和你调用时新建的完全是两个东西,所以打印出来的collectionView是none就很合理了。
怎么解决?
核心就是:找到当前正在显示的那个ViewController实例,再调用它的displayCircle方法,而不是随便new一个新的。
方法1:从Page View Controller拿当前活跃的控制器
假设你持有Page View Controller的引用pageViewController,可以这样获取当前显示的ViewController:
if let currentVC = pageViewController.viewControllers?.first as? ViewController { currentVC.displayCircle() }
方法2:用代理/闭包传递回调(适合跨层级调用)
如果调用方和ViewController不在同一个层级,用代理或者闭包来传递触发信号会更优雅:
- 先定义一个代理协议:
protocol DisplayCircleDelegate: AnyObject { func needDisplayCircle() }
- 在你的ViewController里遵守协议并实现方法:
class ViewController: UIViewController, DisplayCircleDelegate { // ... 你的其他代码 ... func needDisplayCircle() { displayCircle() } }
- 在调用方那边持有代理对象(注意要确保这个代理是当前活跃的ViewController实例):
weak var delegate: DisplayCircleDelegate? // 当需要触发的时候 delegate?.needDisplayCircle()
额外小建议:别用强制解包!
为了代码更安全,建议把displayCircle里的强制解包改成可选绑定,避免以后再踩类似的坑:
func displayCircle() { guard let collectionView = collectionView else { print("⚠️ CollectionView还没加载好,暂时没法添加图层") return } let shapeLayer = CAShapeLayer() shapeLayer.path = circlePath.cgPath shapeLayer.fillColor = UIColor.green.cgColor shapeLayer.strokeColor = UIColor.green.cgColor shapeLayer.lineWidth = 3.0 print(shapeLayer) print(collectionView) collectionView.layer.addSublayer(shapeLayer) }
内容的提问来源于stack exchange,提问作者coder
相关产品推荐
相关产品推荐

