3

モデルに構造体を使用できるかどうかを確認しようとしていますが、これを試していました。を呼び出し vm.testClosure()ても の値は変わらず、そのx理由がわかりません。

struct Model
{
    var x = 10.0
}


var m = Model()

class ViewModel
{
    let testClosure:() -> ()

    init(inout model: Model)
    {
        testClosure =
        {
            () -> () in
            model.x = 30.5
        }
    }
}



var vm = ViewModel(model:&m)

m.x

vm.testClosure()

m.x
4

3 に答える 3

4

引数は値の型への参照ではありません。関数が戻るときに呼び出し元の値に書き戻される値の型inoutの単なるシャドウ コピーです。

コードで起こっていることは、inout変数が関数の有効期間を逃れていることです (クロージャーにキャプチャされて格納されることにより) inout。つまり、関数が返された後の変数への変更は、そのクロージャーの外部に反映されることはありません。

inout引数に関するこの一般的な誤解により、Swift Evolution では、引数をクロージャーによってキャプチャすることのみを許可するという提案がありました。Swift 3 の時点で、現在のコードはコンパイルされなくなります。inout@noescape

コード内で参照を渡す必要がある場合は、参照型を使用する必要があります ( Modelaを作成しますclass)。そもそも参照の受け渡しを回避するために、おそらくロジックをリファクタリングできると思いますが (ただし、実際のコードを確認せずにアドバイスすることはできません)。

編集:この回答を投稿して以来、inoutパラメーターは参照渡しとしてコンパイルできるようになりました。これは、放出されたSILまたはIRを見ることで確認できます。ただし、パラメーターがないため、パラメーターをそのように扱うことはできません関数呼び出しの後、呼び出し元の値が有効なままであることを保証します。)

于 2016-05-05T09:54:00.197 に答える
0

クロージャのインスタンスは、キャプチャされた値の独自の独立したコピーを取得し、それを変更することができます。クロージャの実行時に値が取得されます。少し変更したコードを見てみましょう

struct Model
{
    var x = 10.0

    mutating func modifyX(newValue: Double) {
        let this = self
        let model = m
        x = newValue
// put breakpoint here
//(lldb) po model
//▿ Model
//  - x : 30.0
//
//(lldb) po self
//▿ Model
//  - x : 301.0
//
//(lldb) po this
//▿ Model
//  - x : 30.0            
    }
}

var m = Model()

class ViewModel
{

    let testClosure:() -> ()

    init(inout model: Model)
    {
        model.x = 50
        testClosure =
            { () -> () in
                model.modifyX(301)
        }
        model.x = 30
    }
}

let mx = m.x

vm.testClosure()

let mx2 = m.x
于 2016-05-05T08:57:14.717 に答える
0

これについて、Apple は次のように述べています。

クラスと構造

値型は、変数または定数に割り当てられるとき、または関数に渡されるときにコピーされる型です。[...] Swift では、すべての構造体と列挙型は値型です

メソッド

構造体と列挙型は値型です。既定では、値型のプロパティをそのインスタンス メソッド内から変更することはできません。

ただし、特定のメソッド内で構造体または列挙型のプロパティを変更する必要がある場合は、そのメソッドの動作を変更することを選択できます。その後、メソッドはメソッド内からそのプロパティを変更 (つまり、変更) することができ、メソッドが行ったすべての変更は、メソッドの終了時に元の構造に書き戻されます。このメソッドは、完全に新しいインスタンスを暗黙的な自己プロパティに割り当てることもできます。この新しいインスタンスは、メソッドの終了時に既存のインスタンスを置き換えます。

ここから撮影

于 2016-05-05T09:04:28.923 に答える