美文网首页
Swift4中 结构体中使用闭包再做自我引用时的问题

Swift4中 结构体中使用闭包再做自我引用时的问题

作者: 半日浮生_iOSer | 来源:发表于2018-04-18 15:36 被阅读62次

在swift4中使用结构体时, 在一个闭包中使用Self内的方法或属性时,会报这样错误

 #### “Closure cannot implicitly capture a mutating self parameter”

这是因为swift4没有添加截获列表的原因,其实就是闭包无法保证进出闭包参数的一致性(为什么一致性会不一样你可以去查查swift值类型和引用类型的关系与区别),所以编译器不允许struct在闭包中使用self

一般这种情况有三种解决方案

1. 将类型的struct声明改为class (大多数人都不会选择,这样就将对象从值类型变为了应用类型,可能就改变了我们使用这个类型的初衷,所以不推荐使用)

2.增加一个inout类型的参数 举个例子:

// 这是一个通过Url加载图片的方法  结果返回个带有图片的闭包
func loadImage(imageUrl: String, finish: ((UIImage?)->())?) {
       // 这里做加载图片的处理
}/* 存储图片的结构体
    要求图片Url在设置时自动给image赋值
*/
struct ImageSource {
    var imageURL: String = "" {
        didSet {
            setImage(&self)
        }
    }
    var image: UIImage?
    mutating func setImage(inSelf: inout ImageSource) {
        loadImage(imageUrl: imageURL, finish: { (image) in
            inSelf.image = image
        })
    }}

这种方案虽然也能解决问题但是多了不比必要的内存消耗,inout的声明操作是重新生成一份Self的复制,然后进行修改,修改完成后重新将复制出来的对象赋值self,如果struct比较大,那么就这样做就很不划算

3.使用UnsafeMutablePointer 同样举个例子:

// 这是一个通过Url加载图片的方法  结果返回个带有图片的闭包
func loadImage(imageUrl: String, finish: ((UIImage?)->())?) {
       // 这里做加载图片的处理
}
/* 存储图片的结构体
    要求图片Url在设置时自动给image赋值
*/
struct ImageSource {
    var imageURL: String = "" {
        didSet {
            setImage()
        }
    }
    var image: UIImage?
    func setImage() {
        // 拿到self的指针
        let unsafePointSelf = UnsafeMutablePointer(&self)
        loadImage(imageUrl: imageURL, finish: { (image) in        
            // 进行指针赋值
            unsafePointSelf.pointee.image = image
        })
    }}

这种方式是使用指针进行内存复制,优点是没有多余的内存消耗,性能也高,也不会违背你使用struct的初衷。但是使用UnsafeMutablePointer代表着你必须保证自己代码的安全性,个人推荐使用该方式。

相关文章

网友评论

      本文标题:Swift4中 结构体中使用闭包再做自我引用时的问题

      本文链接:https://www.haomeiwen.com/subject/yiivkftx.html