SwiftUI でよくあるビルドエラーとその解決方法
(1) View要素の並べ過ぎによるビルドエラー
Extra argument in call
ブロック(中括弧{})内に11個以上のView要素を並べるとエラーとなります。
11個以上要素を並べるには、
- HStack・VStackなどで要素を分割する
- 連続したものであれば配列データなどを駆使して 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 については以下の記事でまとめていますのでご参考ください。
コメントを残す