はじめに
前回からの続きでSwiftUIのチュートリアル入門で、[Handling User Input編]になります。
もと記事サイト

Handling user input | Apple Developer Documentation
In the Landmarks app, a user can flag their favorite places, and filter the list to show just their favorites. To create...
Step0
このセッションではObservable Object
を使ってlandmaark dataの変更をViewにバインドさせて反映するための準備をします。
Step1
プロジェクトナビゲーションからModelフォルダーにあるData.swift
を選択します。

Step2
ObservableObject protocol
を準拠した新規Modelを作成するためにCombine
をインポートします。
import Foundation
import Combine
final class ModelData: ObservableObject {
}
var landmarks: [Landmark] = load("landmarkData.json")
func load<T: Decodable>(_ filename: String) -> T {
let data: Data
guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
else {
fatalError("Couldn't find \(filename) from main bundle.")
}
do {
data = try Data(contentsOf: file)
} catch {
fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
}
do {
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
} catch {
fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}
}
Step3
landmarks
の配列を先程宣言したModelData
内に移動します。
import Foundation
import Combine
final class ModelData: ObservableObject {
var landmarks: [Landmark] = load("landmarkData.json")
}
func load<T: Decodable>(_ filename: String) -> T {
let data: Data
guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
else {
fatalError("Couldn't find \(filename) from main bundle.")
}
do {
data = try Data(contentsOf: file)
} catch {
fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
}
do {
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
} catch {
fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}
}
Step4
landmarks
配列の変更を反映するために@Published
を付与します。
import Foundation
import Combine
final class ModelData: ObservableObject {
@Published var landmarks: [Landmark] = load("landmarkData.json")
}
func load<T: Decodable>(_ filename: String) -> T {
let data: Data
guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
else {
fatalError("Couldn't find \(filename) from main bundle.")
}
do {
data = try Data(contentsOf: file)
} catch {
fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
}
do {
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
} catch {
fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}
}
まとめ
今回はModelとView間のデータ変更をバインドするための準備でした。@State
で変数を一つずつ宣言するやり方もありますが、まとめてグループ化したい場合はObservableObject
を準拠させ、@ObservedObject
を使用して変数を宣言します。
コメント