web-dev-qa-db-ja.com

型の不変の値に変更メンバーを使用することはできません

私は次の構造を持っています:

public protocol SuperModel {
    // empty protocol
}
struct ModelOne: SuperModel {
    struct SubModelOne {
        var someVar: Double
        var othervar: Double?
    }
    var sub: SubModelOne?
    mutating func setSub(sub: SubModelOne) {          
        self.sub = sub
    }
}

私のクラスでは、この構造体を次のように使用します。

final class SomeClass: SuperClass {
    var data: SuperModel
    init() {
        self.data = ModelOne()
    }
    func someFunc() {
        (self.data as! ModelOne).setSub(ModelOne.SubModelOne(someVar: 2, otherVar: 1))
    }
}

次のエラーが表示されます:Cannot use mutating member on immutable value of type 'ModelOne'。なぜそうなのか、どうすれば修正できますか?

20
j0h4nn3s

値の型(構造体など)に型キャストを適用すると、成功した場合、要求された値の不変copyを受け取ります。

(self.data as! ModelOne) // this is copy of data

キャストする必要がある値を変更することができる唯一の方法(私に知られているように)-値を再割り当てします(@Sahil Beriが指摘したように、変数を宣言する必要があります):

func someFunc() {
    if var data = data as? ModelOne {
        data.setSub(ModelOne.SubModelOne(someVar: 2, otherVar: 1))
        self.data = data // you can do this since ModelOne conforms to SuperModel
    }
}
27
Shadow Of

Swift 3)では、structclassオブジェクトに変更するだけでエラーを解決できました。

2
Naishta

このように使用し、

struct UserAttributes {
var name:String?
var organizationID:String?
var email:String?

mutating func parseUserAttributes(attribues:[AWSCognitoIdentityProviderAttributeType])->UserAttributes{

    for type in attribues{
        if type.name == "name"{
            name = type.value
        }else if(type.name == "family_name"){
            organizationID = type.value
        }else if(type.name == "custom:role_id"){
            role = type.value
        }else if(type.name == "email"){
            email = type.value
         }

     }

   }  
 }

このような他のファイル呼び出しでは、

var userAttributes = UserAttributes()
userAttributes = userAttributes.parseUserAttributes(attribues:attributes)

問題は、dataSuperModelとして宣言しているが、ModelOneとして割り当てることです。 dataModelOneとして宣言します。その後、問題はなくなります。

final class SomeClass: SuperClass {
    var data: ModelOne
    init() {
        self.data = ModelOne()
    }
    func someFunc() {
        (self.data).setSub(ModelOne.SubModelOne(someVar: 2, otherVar: 1))
    }
}
0
iMuzahid

最初にself.dataをModelOneにダウンキャストしてから、setSub関数を呼び出します

 if var data = self.data as? ModelOne {
   data.setSub(ModelOne.SubModelOne(someVar: 2, othervar: 1))
 }
0
Sahil

@Shadowが正しい。一時的な構造を変更しようとしますが、これは不可能であり、ほとんどの場合、変更が行われると解放されるため、役に立たなくなります。実際、関数の戻り構造体を変更しようとするのと同様の問題です。 (ここの答えを参照してください: プロパティに割り当てることができません:関数呼び出しは不変の値を返します

0
Bioche