LoginSignup
0
1

More than 3 years have passed since last update.

[Swift] protocol制約をかけた型で"Cannot use mutating member on immutable value"と言うエラーが出る場合の対処

Last updated at Posted at 2020-09-20

swift5で次のコードを実行すると

Cannot use mutating member on immutable value: 'hoge' is a 'let' constant

と言うエラーが出ます。これにしばらくハマってしまったので解決方法を書いておきます。

protocol Hoge{
    var items:[String]{get set}
}

class Fuga:Hoge{
    var items: [String]
    init(_ items: [String]){
        self.items = items
    }
}

class Piyo:Hoge{
    var items: [String]
    init(_ items: [String]){
        self.items = items
    }
}

var hoges:[Hoge] = [Fuga(["a"]), Piyo(["a"]), Fuga(["a"])]
hoges.forEach{ (hoge: Hoge) in
    hoge.items.append("b")          //エラー:Cannot use mutating member on immutable value: 'hoge' is a 'let' constant
}

print(hoges.map{$0.items})

items{get set}で宣言しており、問題はないように見えますが、エラーではhogeが定数だと言っています。forEach内で変更しているのが問題なわけでもなく、実際次のコードはすんなり動きます。

var hoges:[Fuga] = [Fuga(["a"]), Fuga(["a"]), Fuga(["a"])]
hoges.forEach{ (hoge: Fuga) in
    hoge.items.append("b")
}

このエラーの原因はprotocolに準拠した型がclassstructか分からないことです。structは基本的に不変なので、もしもHogeに準拠した型がstructだった場合変更ができなくなってしまいます。

ということで、対応にはprotocolclassの制約をかけてあげることです。

protocol Hoge:class{           //ここが大事!!!!
    var items:[String]{get set}
}

class Fuga:Hoge{
    var items: [String]
    init(_ items: [String]){
        self.items = items
    }
}

class Piyo:Hoge{
    var items: [String]
    init(_ items: [String]){
        self.items = items
    }
}

var hoges:[Hoge] = [Fuga(["a"]), Piyo(["a"]), Fuga(["a"])]
hoges.forEach{ (hoge: Hoge) in
    hoge.items.append("b")
}

print(hoges.map{$0.items})

以上です。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1