SwiftUIサンプルの不要なプロトコル
『SwiftUI の Disclosure・Outline・List』記事のため、ドキュメントのいくつかのサンプルを試してみました。
公式ドキュメントのサンプルコードはふえる傾向でその点はありがたいのですが、イマイチのものもありました。
List のサンプルを例に、シンプルになるはずのコードを複雑にしている不要なプロトコルの指定について書きます。
サンプルコードは Xcode 13.1 の Playground で実行しました。
サンプル2
Playground で確認するため何行か追加しています。
import SwiftUI
import PlaygroundSupport
struct ContentView: View {
struct Ocean: Identifiable {
let name: String
let id = UUID()
}
private var oceans = [
Ocean(name: "Pacific"),
Ocean(name: "Atlantic"),
Ocean(name: "Indian"),
Ocean(name: "Southern"),
Ocean(name: "Arctic")
]
var body: some View {
List(oceans) {
Text($0.name)
}
}
}
// playgroundで実行する場合に必要なコード
PlaygroundPage.current.setLiveView(
ContentView()
.frame(width: 300, height: 600) // XcodeのPlaygroundで必要
)
struct Ocean に注目。
Identifiable プロトコルのみでシンプルですが、List での利用には問題ありません。
let id = UUID() これもシンプルで確実、問題ありません。
Supporting Selection in Lists
次の選択できる List のサンプル
struct Ocean: Identifiable, Hashable {
let name: String
let id = UUID()
}
private var oceans = [
Ocean(name: "Pacific"),
Ocean(name: "Atlantic"),
Ocean(name: "Indian"),
Ocean(name: "Southern"),
Ocean(name: "Arctic")
]
@State private var multiSelection = Set<UUID>()
var body: some View {
NavigationView {
List(oceans, selection: $multiSelection) {
Text($0.name)
}
.navigationTitle("Oceans")
.toolbar { EditButton() }
}
Text("\(multiSelection.count) selections")
}
struct Ocean はなぜか Hashable が追加されています。
Hashable を削除しても動作します。
Hashable は不要です。
Supporting Multi-Dimensional Lists
複数行選択のサンプルも不要なプロトコルが書かれています。
次のコードように struct Sea の Hashable は削除しても動作します。
struct ContentView: View {
struct Sea: Identifiable { // Hashable,不要
let name: String
let id = UUID()
}
struct OceanRegion: Identifiable {
let name: String
let seas: [Sea]
let id = UUID()
}
private let oceanRegions: [OceanRegion] = [
OceanRegion(name: "Pacific",
seas: [Sea(name: "Australasian Mediterranean"),
Sea(name: "Philippine"),
Sea(name: "Coral"),
Sea(name: "South China")]),
OceanRegion(name: "Atlantic",
seas: [Sea(name: "American Mediterranean"),
Sea(name: "Sargasso"),
Sea(name: "Caribbean")]),
OceanRegion(name: "Indian",
seas: [Sea(name: "Bay of Bengal")]),
OceanRegion(name: "Southern",
seas: [Sea(name:"Weddell")]),
OceanRegion(name: "Arctic",
seas: [Sea(name: "Greenland")])
]
@State private var singleSelection : UUID?
var body: some View {
NavigationView {
List(selection: $singleSelection){
ForEach(oceanRegions) { region in
Section(header: Text("Major \(region.name) Ocean Seas")) {
ForEach(region.seas) { sea in
Text(sea.name)
}
}
}
}
.navigationTitle("Oceans and Seas")
.toolbar { EditButton() }
}
}
}
Creating Hierarchical Lists
『SwiftUI の Disclosure・Outline・List』記事にも書きましたが、階層表示のサンプルも不要なプロトコル CustomStringConvertible が書かれています。
struct FileItem: Hashable, Identifiable { // , CustomStringConvertible不要
var id: Self { self }
var name: String
var children: [FileItem]? = nil
var description: String {
switch children {
case nil:
return "📄 \(name)"
case .some(let children):
return children.isEmpty ? "📂 \(name)" : "📁 \(name)"
}
}
}
このままだと var id: Self { self } のために Hashable を削除するとエラーが発生し実行できません。
ほかのサンプルと同じように id = UUID() とすると Hashable も不要です。
struct FileItem: Identifiable { // Hashable, CustomStringConvertible不要
var id = UUID() // Self { self } は使わない
var name: String
var children: [FileItem]? = nil
var description: String {
switch children {
case nil:
return "📄 \(name)"
case .some(let children):
return children.isEmpty ? "📂 \(name)" : "📁 \(name)"
}
}
}
ひとつのページのサンプルで Identifiable の実装がいろいろなのは初学者向けとは言えないと思います。
まとめ
🟠 Apple公式ドキュメントのサンプルは充実してきたがいまいちのものもある
🟠 参考にする場合は自分で確認しよう
🟠 ドキュメントのサンプルを試すには Playground が最適
こちらの記事もぜひご覧ください。
有料記事ですがおよそ半分試読できます。
この記事を含むマガジンもあります。