Нельзя использовать мутирующий элемент по неизменяемому значению типа

У меня есть следующая структура:

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'. Почему это так и как я могу это исправить?

Ответ 1

Когда вы применяете тип casting к типам значений (такие структуры), если они успешны, вы получаете неизменяемую копию запрашиваемого значения:

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

Ответ 2

В Swift 3, в моем случае, я смог разрешить ошибку, просто изменив struct на объект class.

Ответ 3

Проблема в том, что вы объявили data как SuperModel, но выделили ее как ModelOne. Объявите data как ModelOne. Тогда проблема уходит.

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

Ответ 4

Сначала сбрасываем self.data в ModelOne, затем вызываем функцию setSub

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

Ответ 5

@Правая. Вы пытаетесь изменить временную структуру, которая невозможна и большую часть времени бесполезна, поскольку она будет выпущена после того, как будет выполнена мутация. На самом деле это аналогичная проблема с попыткой изменить структуру возврата функции. (см. ответ здесь: Нельзя назначить свойство: вызов функции возвращает неизменяемое значение)

Ответ 6

Используйте как это,

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)