swift - Swift3 中 Struct 和 Class 异步变异的不同过程

标签 swift class asynchronous struct swift3

在结构类型中,在异步过程中改变自身会产生如下错误。

闭包无法隐式捕获变异的自身

如果我将结构更改为类类型,错误就会消失。 structclass 异步 mutate self 时有什么区别?

struct Media {
static let loadedDataNoti = "loadedDataNotification"
let imagePath: String
let originalPath: String
let description: String
var imageData: Data?
let tag: String
var likeCount: Int?
var commentCount: Int?
var username: String?
var delegate: MediaDelegate?

public init(imagePath: String, originalPath: String, description: String, tag: String, imageData: Data? = nil) {
    self.imagePath = imagePath
    self.originalPath = originalPath
    self.description = description
    self.tag = tag

    if imageData != nil {
        self.imageData = imageData
    } else {
        loadImageData()
    }
}

mutating func loadImageData() {
    if let url = URL(string: imagePath) {
        Data.getDataFromUrl(url: url, completion: { (data, response, error) in
            if (error != nil) {
                print(error.debugDescription)
                return
            }
            if data != nil {
                self.imageData = data! // Error: closure cannot implicitly captured a mutating self
                NotificationCenter.default.post(name: NSNotification.Name(rawValue: Media.loadedDataNoti), object: data)
            }
        })
    }
}

最佳答案

结构是一种值类型。结构变异如何工作?它通过创建一个全新的结构并将其替换为原始结构来工作。即使在像这样的简单情况下:

    struct S {
        var name = "matt"
    }

    var s = S()
    s.name = "me"

...您实际上是在用另一个 S 实例替换 — 这就是为什么必须将 s 声明为 var 以便这样做。

因此,当您将结构的 self 捕获到异步执行的闭包中并要求对其进行变异时,您可能会在未来某个时间突然出现并撕掉现有结构并用另一个替换它一个正在执行这段代码。这是一个不连贯的概念,编译器正确地阻止了你。它是不连贯的,尤其是因为你怎么知道那个时候这个相同的 self 甚至会存在?一个干预突变可能已经破坏并取代了它。

因此,这是合法的:

struct S {
    var name = "matt"
    mutating func change() {self.name = "me"}
}

但这不是:

func delay(_ delay:Double, closure:@escaping ()->()) {
    let when = DispatchTime.now() + delay
    DispatchQueue.main.asyncAfter(deadline: when, execute: closure)
}

struct S {
    var name = "matt"
    mutating func change() {delay(1) {self.name = "me"}} // error
}

关于swift - Swift3 中 Struct 和 Class 异步变异的不同过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41076117/

相关文章:

swift - 如何在 WidgetKit 中重置意图扩展配置

ios - 如何阻止 Alamofire 对 URL 参数进行编码

javascript - 仅将点击事件应用于目标类 jQuery

python - 如何在 Python 类中更好地分离数据

java - Java多个文件和文件夹层次结构

javascript - 如何在 jQuery 1.8.x 中链接一系列延迟函数?

ios - 在 Swift 5 协议(protocol)中使用 @objc

ios - apple API 中的变量 "bounds.minX", "bounds.maxX"定义在哪里?

C# 在 UdpClient 接收上使用异步/等待

asp.net - 在 ASP.NET WebService 中启动一个线程