SKAction逃逸闭包捕获inout参数报错,求解决方案
解决Swift中逃逸闭包捕获inout参数的错误
错误原因
Swift的inout参数通过传递值的内存地址实现,函数执行结束后,该地址的有效性不再被编译器保证。而你使用的SKAction.run(_:completion:)的闭包属于逃逸闭包——它会在函数返回后(动画完成时)才执行,此时去捕获inout参数pool,编译器无法确保闭包执行时pool的内存地址仍然有效,因此抛出错误。
可行解决方案
方案1:将数组包装为引用类型(推荐)
结构体是值类型,inout只是模拟引用传递;而类是真正的引用类型,直接传递类实例即可让闭包安全捕获并修改内部数组。
- 定义数组包装类:
class ObjectPool { var items: [Object] = [] }
- 修改
spill函数:
func spill(pool: ObjectPool) { // 先判空,避免数组越界崩溃 guard !pool.items.isEmpty else { return } let spill = pool.items[0] spriteComponent.node.addChild(spill.sprite) pool.items.removeFirst() spill.sprite.run(SKAction.sequence([spill.spriteAnimation, SKAction.removeFromParent()])) { pool.items.append(spill) // 执行其他操作 } }
- 调用函数:
// 假设objectPool是ObjectPool类的实例 spill(pool: objectPool)
方案2:使用UnsafeMutablePointer(不推荐,需注意内存安全)
如果不想修改原有数据类型,可以通过指针临时持有数组地址,但必须确保闭包执行前数组的内存始终有效(比如数组不会被销毁、不会因扩容重新分配内存):
func spill(pool: inout [Object]) { guard !pool.isEmpty else { return } let spill = pool[0] spriteComponent.node.addChild(spill.sprite) pool.removeFirst() // 用指针持有数组地址 let poolPtr = UnsafeMutablePointer(&pool) spill.sprite.run(SKAction.sequence([spill.spriteAnimation, SKAction.removeFromParent()])) { poolPtr.pointee.append(spill) // 执行其他操作 } }
方案选择建议
优先使用方案1,类的引用类型天然适配这种跨异步操作修改共享数据的场景,代码更安全、易维护,无需手动关注内存安全问题。
内容的提问来源于stack exchange,提问作者Bob
相关产品推荐
相关产品推荐

