【初学者向け】SwiftUI でよくあるビルドエラー3選とその解決方法

SwiftUI でよくあるビルドエラーとその解決方法

(1) View要素の並べ過ぎによるビルドエラー

Extra argument in call

ブロック(中括弧{})内に11個以上のView要素を並べるとエラーとなります。

11個以上要素を並べるには、

  • HStackVStackなどで要素を分割する
  • 連続したものであれば配列データなどを駆使して ForEach で表示する

のどちらかで対応できます。

VStack で分割する例
struct ContentView: View {
    var body: some View {
        VStack {
            Text("Text01")
            Text("Text02")
            Text("Text03")
            Text("Text04")
            Text("Text05")
            Text("Text06")
        }
        VStack {
            Text("Text07")
            Text("Text08")
            Text("Text09")
            Text("Text10")
            Text("Text11")
        }
    }
}
ForEach でまとめる例
struct ContentView: View {
    let data: [String] = [
        "Text01",
        "Text02",
        "Text03",
        "Text04",
        "Text05",
        "Text06",
        "Text07",
        "Text08",
        "Text09",
        "Text10",
        "Text11"
    ]
    var body: some View {
        ForEach(data, id: \.self) { text in
            Text(text)
        }
    }
}

(2)「$」接頭辞の付加忘れ、付加位置の誤りによるビルドエラー

  • Cannot convert value of type ‘Bool’ to expected argument type ‘Binding<Bool>’
  • Cannot convert value of type ‘Published<Bool>.Publisher’ to expected argument type ‘Binding<Bool>’

※Bool は Int や String にも置き換えられます。

前者は、状態変数のバインディングに必要な接頭辞「$」の付け忘れによるもの、後者は$」の位置が誤っています

前者は、エラーの赤丸クリックに表示される Fix ボタンで修正されすぐわかると思いますが、後者はハマりやすいポイントだと思います(筆者もSwiftUI初心者の頃ハマりました)。

後者は正しくは以下のように ViewModel 側の頭に付けます。

.alert(isPresented: $viewModel.showingAlert)

(3) List・ForEach の id 付加漏れ

Initializer ‘init(_:rowContent:)’ requires that ‘String’ conform to ‘Identifiable’

List と ForEach に渡す配列のデータ型は、Identifiable プロトコルに準拠する必要があります

上記の例でStringの配列を渡していますが、String は Identifiable を継承していません

そのため、Int や String 配列を渡したい場合は以下のように、ちょっと特殊な書き方をする必要があります。

List(data, id: \.self) { text in
    Text(text)
}

引数 id: に \.self を代用することでこのエラーを回避できます。

独自に定義した構造体データを使いたい場合は Identifiable に準拠させれば引数の id 指定は不要です

struct User: Identifiable {
    let id = UUID()
    let name: String
    let age: Int
}

struct ContentView: View {
    let users: [User] = [
        User(name: "User0001", age: 18),
        User(name: "User0002", age: 35),
        User(name: "User0003", age: 42),
        User(name: "User0004", age: 3),
        User(name: "User0005", age: 84)
    ]
    var body: some View {
        List(users) { user in
            HStack {
                Text("名前:\(user.name)さん")
                Spacer().frame(width: 32)
                Text("年齢:\(user.age)歳")
            }
        }
    }
}

なお、データ型に id を含ませたくない場合は、\.self を使うことになりますが、その場合、そのデータ型は Hashable プロトコルを継承しておく必要があります

struct User: Hashable {
    let name: String
    let age: Int
}

struct ContentView: View {
    let users: [User] = [
        User(name: "User0001", age: 18),
        User(name: "User0002", age: 35),
        User(name: "User0003", age: 42),
        User(name: "User0004", age: 3),
        User(name: "User0005", age: 84)
    ]
    var body: some View {
        List(users, id: \.self) { user in
            HStack {
                Text("名前:\(user.name)さん")
                Spacer().frame(width: 32)
                Text("年齢:\(user.age)歳")
            }
        }
    }
}

以上、SwiftUI の Viewレイアウトでよくあるビルドエラーについて解説しました。

List、ForEach については以下の記事でまとめていますのでご参考ください。

【おすすめの関連記事】