iOSアプリを作るためにSwift UIを勉強していて気になったところ
自分が直感でわからなかったところ、忘れてしまっていたところを主に残しておく
文字列埋め込み
以下のようにバックスラッシュと()を使用して、変数を埋め込める ※Macでは「option + ¥」でバックスラッシュを入力可能
let name = "taro" print("\(name)さん こんにちは!")
デバッグログ出力
print("xxx")で出力可能。
(メニューの「View」→「Debug Area」→「Activate Console」でConsoleが開き、そこで出力が確認できる)
import SwiftUI struct ContentView: View { var body: some View { VStack { Button(action: output){ Text("call") } } } func output() { print("Hello World") } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
データモデルの作り方
「File」→「New」→「File...」→「Data Model」を選択
任意の名前を付ける
画面下部の「Add Entity」でEntityを作成する
Atrributes欄の「+」ボタンを押下して、Attributeを追加する
※個人的な理解としてはEntityがテーブル、Attributesがカラムである認識
データモデルの使い方
- Persistenceを扱うファイルを作成する
適当にswiftファイルを作成してPersistenceを扱う構造体を作成する
import CoreData ⭐️ struct PersistenceController { // NSPersistentContainerを定義する let container: NSPersistentContainer init() { // 引数にはModel Fileの名前を入れる container = NSPersistentContainer(name: "MyCoreDataModel") ⭐️ container.loadPersistentStores(completionHandler: {(storeDescription, error) in if let error = error as NSError? { fatalError("error = \(error), userInfo = \(error.userInfo)") } }) } }
- エントリポイントでPersistenceを扱う構造体から「viewContext」を取得して、Viewの環境変数に入れる
import SwiftUI @main struct WorkingApp: App { let persistenceController = PersistenceController() var body: some Scene { WindowGroup { ContentView() .environment(\.managedObjectContext, persistenceController.container.viewContext) ⭐️ } } }
- viewContextの取り出し
呼び出し先の「ContentView」では以下のように実装する
struct ContentView: View { @Environment(\.managedObjectContext) var viewContext ⭐️環境変数から「viewContext」を取り出し var body: some View { VStack { SubView().environment(\.managedObjectContext, viewContext) ⭐️他のViewを呼び出す際にも、同じようにそのViewの環境変数にセットすればviewContextを渡せる } }
- DBへのアクセス
「@FetchRequest(sortDescriptors: [])」でソート方法を指定(※空配列を指定する場合は、指定なしとなる) FetchedResultsで「Entity」を指定して変数を定義する
truct SubView: View { @Environment(\.managedObjectContext) var viewContext @FetchRequest(sortDescriptors: []) ⭐️ var humans: FetchedResults<HumanData> ⭐️HumanDataというEntityを作成した場合の例 var body: some View { List { ForEach(humans) { human in Text(human.name!) ⭐️値取り出し } Button(action: addHuman) { Text("add") ⭐️追加ボタン } Button(action: deleteHuman) { Text("delete") ⭐️削除ボタン } } } func addHuman() { let newHuman = HumanData(context: viewContext) ⭐️新しいレコードを作成する newHuman.name = "テストマン" do { try viewContext.save() ⭐️保存 } catch { print("error") fatalError("失敗") } } func deleteHuman() { for human in humans { viewContext.delete(human) ⭐️該当のレコードを削除 } do { try viewContext.save() ⭐️保存 } catch { print("error") fatalError("失敗") } }
HStack VStack
HStack: 横並び VStack: 縦並び
for
こんな感じで記述する(1...10とすれば1~10まで回せる) ※以下の例は9まで表示
for i in 1..<10 { print(i) }
Swift UIのForEach
Listにネストして以下のように使用できる
struct ForEachPractice: View { var body: some View { List { ForEach(0...10) { num in Text("\(num) !") } } } }
Viewの更新
参考:SwiftUIの機能 @State, @ObservedObject, @EnvironmentObjectの違いとは| 開発者ブログ | 株式会社アイソルート
@State
@Stateを使用すると、その変数の更新時にViewが更新される
import SwiftUI struct StatusPractice: View { @State var test = "xxx" ⭐️ struct内では、@Stateを使用しなければ値を変更できないぽい var body: some View { VStack { Button(action: {self.test = "yyy"}) { Text("call") } Text(test) } } }
@ObservedObject
@ObservedObjectを使用すると、クラスの特定の変数(@Publishedをつけた変数)の更新を検知してViewが更新される
struct ObservedObjectPractice: View { @ObservedObject var testData = TestData(v: "xxx") ⭐️@ObservedObjectを使用 var body: some View { VStack { Button(action: {self.testData.value = "yyy"}) { Text("call") } Text(testData.value) } } } class TestData: ObservableObject { ⭐️ObservableObjectを継承 @Published var value: String ⭐️@Publishedをつけた変数が更新されるとViewが更新される init (v: String) { self.value = v } }
@EnvironmentObject
@EnvironmentObjectを使用すると、@ObservedObjectと同様にクラスの特定の変数の変更を検知してViewが更新される @ObservedObjectとの違いは、複数のViewで共通のインスタンスを参照できる(アプリ全体の共通プロパティとして扱われるよう)
つまり、アプリ全体で共通のプロパティとなります。
以下の例ではContentView1、ContentView2でもxxx→yyyに変更されることが確認できる
import SwiftUI truct EnviromentObjectPractice: View { @EnvironmentObject var testData: TestData ⭐️@EnvironmentObjectを使用 var body: some View { VStack{ Button(action: {self.testData.value = "yyy"}){ Text("call") } Text("ParentView: \(testData.value)") ContentView1() ContentView2() } } } class TestData: ObservableObject { @Published var value: String ⭐️@Publishedをつけた変数が更新されるとViewが更新される init (v: String) { self.value = v } } struct ContentView1:View { @EnvironmentObject var testData: TestData var body: some View { Text("ContentView1: \(testData.value)") } } struct ContentView2:View { @EnvironmentObject var testData: TestData var body: some View { Text("ContentView2: \(testData.value)") } } struct EnviromentObjectPractice_Previews: PreviewProvider { static var previews: some View { EnviromentObjectPractice().environmentObject(TestData(v:"xxx")) ⭐️「environmentObject」で呼び出し側から値を指定する } }