三. 项目中遇到的一些的报错问题
3-1. "Closure cannot implicitly capture a mutating self parameter"错误
在struct中,如果我们在闭包中使用self,就会得到Closure cannot implicitly capture a mutating self parameter的错误提示。比如:
struct RecordModel {
/// 定义一个闭包
var action: (() -> ())?
var height = 10
self.action = {
self.height = 20
//Closure cannot implicitly capture a mutating self parameter报错
}
}
++并且由于RecordModel的类型是struct,我们也没发在action闭包里添加截获列表。那么是不是就必须使用class了?答案是否定的。有两种方式可以解决这个问题。++
方案一:为closure增加一个inout类型的参数
struct RecordModel {
/// 定义一个闭包
var action: ((_ inSelf: inout RecordModel) -> ())?
var height = 10
self.action = { (inSelf) in
inSelf.height = 20
}
}
根据inout类型的说明,我们知道,实际上这相当于增加了一个隐藏的临时变量,self被复制,然后在closure(闭包)中使用,完成后,再复制回self。也就是说,这个方法有额外的内存开销。如果是struct较大的情形,这么做并不划算。
方案二:使用UnsafeMutablePointer<Pointee>
==这次采用直接指针的方式对于struct来进行操作,采用指针的好处是self不会被多次复制,性能较高。缺点是你需要自行确定你的代码的安全。==
struct RecordModel {
/// 定义一个闭包
var action: (() -> ())?
var height = 10
let selfPointer = UnsafeMutablePointer(&self)
self.action = {
selfPointer.pointee.height = 20
}
}
结论
==Closure cannot implicitly capture a mutating self parameter错误的原因是在进出closure(闭包)之后,self的一致性没办法得到保证,所以编译器默认不允许在struct的closure(闭包)中使用self。如果我们确定这么做是安全的,就可以通过上面的两种方式解决这个问题。其中,方法二的性能更好一些。==
注意
这里可以记一下指针和swift变量之间的关系:
UnsafePointer对应let UnsafeMutablePointer对应var AutoreleasingUnsafeMutablePointer对应unowned UnsafeMutablePointer,用于inout的参数类型 UnsafeRawPointer对应let Any,raw系列都是对应相应的Any类型 UnsafeBufferPointer是non-owning的类型(unowned),用于collection的elements, buffer系列均如此3-2. Declarations from extensions cannot be overridden yet 错误
==这个错误大致是因为,协议方法是在extension里面的,不能被重写==
解决办法:(仅供参考,如有更好的建议还望多多指教)
小编想到的解决办法就是在每一个需要此协议的类里面,重新遵循代理,实现该协议方法








