Swift3中结构和类异步变异的不同过程

Swift3中结构和类异步变异的不同过程,swift,class,asynchronous,struct,swift3,Swift,Class,Asynchronous,Struct,Swift3,在struct类型中,在异步进程中修改self会产生如下错误 闭包无法隐式捕获变异的自我 如果我将结构更改为类类型,错误就会消失。 当以异步方式改变self时,struct和class之间有什么区别 struct Media { static let loadedDataNoti = "loadedDataNotification" let imagePath: String let originalPath: String let description: String var imageDa

在struct类型中,在异步进程中修改self会产生如下错误

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

如果我将结构更改为类类型,错误就会消失。 当以异步方式改变self时,
struct
class
之间有什么区别

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)
            }
        })
    }
}

当您对值类型的实例(如结构)进行变异时,您在概念上是将其替换为同一类型的新实例,即:

myMedia.mutatingFuncToLoadImageData()
…可以被认为是这样做的:

myMedia = Media(withLoadedData: theDownloadedData)
    struct S {
        var name = "matt"
    }

    var s = S()
    s.name = "me"
…除非你看不到代码中的赋值

实际上,您正在替换调用上的
mutating
函数的实例。在这种情况下,
myMedia
。正如您可能意识到的,为了使其工作,变异必须在变异函数的末尾完成,否则您的实例在调用变异函数后将继续更改

您正在将对
self
的引用传递给一个异步函数,该函数将在变异函数结束后尝试变异您的实例

您可以通过执行以下操作来编译代码

var myself = self // making a copy of self
let closure = {
    myself.myThing = "thing"
}

但这只会更改变量的值,而不会影响函数之外的任何内容。

当您更改值类型的实例(如结构)时,您在概念上用相同类型的新实例替换它,即:

myMedia.mutatingFuncToLoadImageData()
…可以被认为是这样做的:

myMedia = Media(withLoadedData: theDownloadedData)
    struct S {
        var name = "matt"
    }

    var s = S()
    s.name = "me"
…除非你看不到代码中的赋值

实际上,您正在替换调用上的
mutating
函数的实例。在这种情况下,
myMedia
。正如您可能意识到的,为了使其工作,变异必须在变异函数的末尾完成,否则您的实例在调用变异函数后将继续更改

您正在将对
self
的引用传递给一个异步函数,该函数将在变异函数结束后尝试变异您的实例

您可以通过执行以下操作来编译代码

var myself = self // making a copy of self
let closure = {
    myself.myThing = "thing"
}

但这只会更改变量的值,而不会影响函数之外的任何内容。

结构是一种值类型。结构突变是如何工作的?它的工作原理是创建一个全新的结构并用它替换原来的结构。即使在这样简单的情况下:

myMedia = Media(withLoadedData: theDownloadedData)
    struct S {
        var name = "matt"
    }

    var s = S()
    s.name = "me"
。。。实际上,您正在用另一个实例替换一个实例-这就是为什么必须将
S
声明为
var
才能执行此操作的原因

这样,当你将一个Stutt的<代码>自我/代码>捕获到一个异步执行的闭包中并要求对它进行突变时,你威胁会在将来某个时间出现,并突然撕开现有的结构,并在执行这段代码的过程中用另一个结构替换它。这是一个不连贯的概念,编译器正确地阻止了您。这是不连贯的,尤其是因为你怎么知道这个相同的

自我
在那个时候还会存在?中间的突变可能已经破坏并取代了它

因此,这是合法的:

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
}

结构是一种值类型。结构突变是如何工作的?它的工作原理是创建一个全新的结构并用它替换原来的结构。即使在这样简单的情况下:

myMedia = Media(withLoadedData: theDownloadedData)
    struct S {
        var name = "matt"
    }

    var s = S()
    s.name = "me"
。。。实际上,您正在用另一个实例替换一个实例-这就是为什么必须将
S
声明为
var
才能执行此操作的原因

这样,当你将一个Stutt的<代码>自我/代码>捕获到一个异步执行的闭包中并要求对它进行突变时,你威胁会在将来某个时间出现,并突然撕开现有的结构,并在执行这段代码的过程中用另一个结构替换它。这是一个不连贯的概念,编译器正确地阻止了您。这是不连贯的,尤其是因为你怎么知道这个相同的

自我
在那个时候还会存在?中间的突变可能已经破坏并取代了它

因此,这是合法的:

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
}

使此代码在
中的函数变为mutating
。像这样
mutating func(){//your code}
。函数声明为
mutating
?@尽管我尝试过。但是结果是一样的。发布更多的代码。添加完整的代码。使此代码所在的函数发生变化。像这样
mutating func(){//your code}
。函数声明为
mutating
?@尽管我尝试过。但是结果是一样的。发布更多的代码。添加完整的代码。问题集中在引用和复制的不同方式上。谢谢。问题集中在不同的参考和复制方式上。谢谢