Cannot use mutating member on immutable value of type

痞子三分冷 提交于 2020-06-22 09:27:06

问题


I have following struct:

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

In my class, I want to use this struct like that:

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

I get following error: Cannot use mutating member on immutable value of type 'ModelOne'. Why is that so and how can I fix this?


回答1:


When you apply type casting to value types (such structs), if succeed, you receive immutable copy of requested value:

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

The only way (as known to me) how you can mutate values that need to be casted - reassign value (as @Sahil Beri pointed you need declare variable):

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



回答2:


In Swift 3, in my case, I was able to resolve the error just by changing struct to a class object.




回答3:


Use like this,

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
         }

     }

   }  
 }

In some other file call like this,

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



回答4:


Problem is that you have declared data as SuperModel but allocate it as ModelOne. Declare data as ModelOne. Then the problem goes away.

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



回答5:


First downcast the self.data to ModelOne then call setSub function

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



回答6:


@Shadow of is right. You try to mutate a temporary structure which is impossible and most of the time useless as it will be released once the mutation done. It's in fact a similar issue to trying to modify the return struct of a function. (see answer here : Cannot assign to property: function call returns immutable value)



来源:https://stackoverflow.com/questions/38764003/cannot-use-mutating-member-on-immutable-value-of-type

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!