Xcode报错:Call to method ‘DownloadCryptocurrencyImages’ in closure requires explicit use of ‘self’ to make capture semantics explicit
Xcode报错:Call to method ‘DownloadCryptocurrencyImages’ in closure requires explicit use of ‘self’ to make capture semantics explicit

Xcode报错:Call to method ‘DownloadCryptocurrencyImages’ in closure requires explicit use of ‘self’ to make capture semantics explicit

问题描述

当我尝试在SwiftUI中调用dataTask方法下载数据后,使用DownloadCryptocurrencyImages()方法在dataTask方法中缓存图片时,发现如下报错:

Call to method 'DownloadCryptocurrencyImages' in closure requires explicit use of 'self' to make capture semantics explicit

报错代码:

func fetchCryptoData(context: NSManagedObjectContext) {
    let task = URLSession.shared.dataTask(with: apiURL) { data, response, error in  // URLSession方法闭包
        // 检查响应数据
        if let data = data {
            // 下载加密货币的图片
            DownloadCryptocurrencyImages(imageURL: coin.image, imageName: coin.symbol)  // 报错代码
        }
    }
    task.resume()   // 启动任务
}

问题原因

问题原因在于报错代码DownloadCryptocurrencyImages是一个实例方法,当在闭包(URLSession下载)或异步上下文中调用时,Swift会要求显式加上self,这是强调引用实例自身的方法。

这是Swift的语法规范,避免在闭包中捕获self,导致内部泄漏。

在Swift中,普通的方法:

func DownloadCryptocurrencyImages(imageURL: URL, imageName: String) {
    // 逻辑不重要
}

如果实在类中定义的:

class MyViewModel {
    func DownloadCryptocurrencyImages(...) {
        ...
    }
}

这就不是普通的方法,而是实例方法,调用它时其实等价于:

self.DownloadCryptocurrencyImages(...)

在Swift的闭包中使用 self.属性 或者 self.方法 ,Swift会强制要求显式写出self,避免无意识的捕获self,从而造成内存泄漏。

解决方案

这个问题的解决方案很简单,点击Xcode提示的fix按钮:

Reference 'self.' explicitly
Capture 'self' explicitly to enable implicit 'self' in this closure

在报错方法前面添加self:

// 下载加密货币的图片
self.DownloadCryptocurrencyImages(imageURL: coin.image, imageName: coin.symbol)

或者在闭包中开启弱引用:

func fetchCryptoData(context: NSManagedObjectContext) {
    let task = URLSession.shared.dataTask(with: apiURL) { [self] data, response, error in   // 添加[self]以捕获self引用
        // 检查响应数据
        if let data = data {
            // 下载加密货币的图片
            DownloadCryptocurrencyImages(imageURL: coin.image, imageName: coin.symbol)  // 报错代码
        }
    }
    task.resume()   // 启动任务
}

如果不想用self,可以定义为static方法(类方法,不依赖self)。

class MyViewModel {
    static func DownloadCryptocurrencyImages(...) {
        ...
    }
}

也可以写在类的外卖,变成自由函数(全局函数)。

func DownloadCryptocurrencyImages(...) {
    ...
}

这样就可以在任何地方调用它,并且不用写self。

总结

只要定义在类(或结构体)内的方法,都是实例方法,在闭包中调用时必须使用.self。

   

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开发者。

欢迎加入我们的 微信交流群QQ交流群,交流更多精彩内容!
微信交流群二维码 QQ交流群二维码

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注