2016-12-10 5 views
0

構造体型では、非同期処理でselfを突然変異させると以下のようにエラーが発生します。Swift3で非同期に突然変異する構造体とクラスの異なる処理

closure cannot implicitly captured a mutating self

私はクラス型への構造体を変更した場合は、エラーが消えます。 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) 
      } 
     }) 
    } 
} 
+0

は、このコードはmutating' 'である機能を確認します。この 'func(){//あなたのコード}を変更する'のように。 – shallowThought

+0

関数は 'mutating'宣言されていますか? –

+0

@shallowThought私は試しました。しかし結果は同じでした。 –

答えて

1

構造体は値型です。 struct mutatingはどのように機能しますか?これは、完全に構造体に置き換え、を元に戻してとすることによって機能します。でも、このような単純な場合には: - sこれを行うためにvarとして宣言されなければならない理由を正確である

struct S { 
     var name = "matt" 
    } 

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

...あなたは別のことで 1つのSインスタンスを置き換える実際です。

したがって、構造体の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 
} 
+0

問題は、参照とコピーのさまざまな方法に焦点が当てられていました。ありがとう。 –

1

あなたが値型のインスタンス変異させる - などの構造体などを - あなたは、概念的には、このやっすなわち、同じタイプの新しいインスタンスで置き換えている:

myMedia.mutatingFuncToLoadImageData() 

を...このようなことをすると考えることができます:

...コードでの割り当ては表示されません。

mutating関数のインスタンスを効果的に置き換えています。この場合、myMedia。理解できるように、これが機能するためには、突然変異関数の終わりに突然変異が終了していなければなりません。あるいは、突然変異関数を呼び出した後にインスタンスが変化し続けることもあります。

への参照を、の突然変異関数が終了した後にインスタンスを突然変異させようとする非同期関数に引き渡しています。

あなたが

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

ような何かをすることによって、あなたのコードをコンパイルすることができますが、それは唯一の変数myselfの値を変更し、あなたの関数の外では何も影響しません。

関連する問題