在结构类型中,在异步过程中改变自身会产生如下错误。
闭包无法隐式捕获变异的自身
如果我将结构更改为类类型,错误就会消失。
struct
和 class
异步 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/