SKShapeNode子类draw方法访问self.scene为nil问题求解
问题成因
- SKNode(包括你子类化的SKShapeNode)的
scene属性,只有当节点已经被正式加入到场景的节点树中时才会被赋值,未被添加到场景的节点访问scene属性必然返回nil。 - 你的代码执行顺序逻辑存在问题:在
addOuterMovingBlocks方法中,你先执行了shape.setup(number: 1),这个方法内部调用draw(_:)时会访问scene属性,而此时你还没有执行addChild(shape)把节点挂载到场景上,自然取不到值。 - 你把代码全部迁移到GameScene中就能正常运行,是因为你直接访问的是GameScene本身的属性,不需要依赖节点挂载后的
scene属性获取场景实例。
修复方案
你可以调整代码执行顺序,或者修改参数传递逻辑来解决问题,两种常用方案如下:
方案1:调整节点挂载和初始化的顺序
先把节点添加到场景,再执行初始化配置:
private func addOuterMovingBlocks() { let shape = ExternalRingNode() // 先挂载到场景 addChild(shape) // 再执行setup,此时scene属性已经有值 shape.setup(number: 1) }
方案2:把需要的参数直接传递给自定义节点,不需要依赖scene属性
这种方案耦合度更低,也更符合组件化设计思路:
// 修改ExternalRingNode的setup方法,直接接收需要的参数,比如这里你要用到的blocksCount func setup(number: Int, blocksCount: Int) { path = draw(number, blocksCount: blocksCount).cgPath } func draw(_ number: Int, blocksCount: Int) -> UIBezierPath { // 不需要再访问scene属性,直接用传入的参数即可 return UIBezierPath() } // 调用时直接从GameScene传值 private func addOuterMovingBlocks() { let shape = ExternalRingNode() shape.setup(number: 1, blocksCount: blocksCount) addChild(shape) }
内容的提问来源于stack exchange,提问作者gmb55
相关产品推荐
相关产品推荐

