しめ鯖日記

swift, iPhoneアプリ開発, ruby on rails等のTipsや入門記事書いてます

SwiftUIを触ってみる

SwiftUIで簡単なUIを作ってみました。

まずはXcode11で新規プロジェクトを作成します。

f:id:llcc:20191201174101p:plain

テンプレートは「Single View App」を選びました。

f:id:llcc:20191201174134p:plain

プロジェクト構成は以下のようになっています。

f:id:llcc:20191201175809p:plain

Xcode11からはSceneDelegate.swiftというファイルが追加されています。 これはiPadで画面に複数アプリ表示する際に使うクラスで、今までのAppDelegateの役割の一部を担っています。 今回はSwiftUIを中心に見たいので深堀りしないことにします。

まずはアプリを立ち上げてみます。 アプリを起動すると下のようにHello, World!と表示されます。

f:id:llcc:20191201180656p:plain

その下にラベルを1つ追加してみたいと思います。 ContentViewクラスを以下のように修正します。 2つ縦に並べるのはVStackというクラスを使っています。

struct ContentView: View {
    var body: some View {
        VStack {
            Text("Hello, World!")
            Text("Goodnight, World!")
        }
    }
}

アプリを起動するとラベルが2つ表示されています。

f:id:llcc:20191201180957p:plain

次にラベル間を少し空けてみます。 VStackの初期化時にspacingを渡します。

struct ContentView: View {
    var body: some View {
        VStack(spacing: 200) {
            Text("Hello, World!")
            Text("Goodnight, World!")
        }
    }
}

これで間隔を200pxにする事ができました。

f:id:llcc:20191201181253p:plain

ラベルと色やフォントも変更してみます。

struct ContentView: View {
    var body: some View {
        Text("Hello, World!").font(Font.system(size: 50)).foregroundColor(Color(red: 1, green: 1, blue: 0))
    }
}

少し見づらいですが黄色の大きめの文字に変わりました。

f:id:llcc:20191201182626p:plain

次はボタンの追加とタップ時のアクション追加を行います。

struct ContentView: View {
    var body: some View {
        Button("ボタン") {
            print(10)
        }
    }
}

ボタンをタップするとデバッグエリアに10が表示されます。

f:id:llcc:20191201181647p:plain

次はボタンタップ時にアラートも表示してみます。

struct ContentView: View {
    @State var isPresented = false
    
    var body: some View {
        Button("ボタン") {
            self.isPresented = true
        }.alert(isPresented: $isPresented) {
            Alert(title: Text("Title"), message: Text("Message"))
        }
    }
}

アラートを表示する事ができました。

f:id:llcc:20191201183827p:plain

この.alert(isPresented:)はButtonに付いている必要はなく以下のようにTextに付いていても動きます。

struct ContentView: View {
    @State var isPresented = false
    
    var body: some View {
        VStack {
            Text("Hello, World!").alert(isPresented: $isPresented) {
                Alert(title: Text("Title"), message: Text("Message"))
            }
            Button("ボタン") {
                self.isPresented = true
            }
        }
    }
}

次はボタンを押した時にテキストの内容を変える処理をします。

struct ContentView: View {
    @State var text = "Hello, World"
    
    var body: some View {
        VStack {
            Text(text)
            Button("ボタン") {
                self.text = "Goodnight, World"
            }
        }
    }
}

ボタンを押すとテキストを変更する事ができました。

f:id:llcc:20191201184821p:plain

以下のようにViewModelを別途作る事もできます。

class MyViewModel : ObservableObject, Identifiable {
    @Published
    var text: String = "Hello, World"
}

struct ContentView: View {
    @ObservedObject var viewModel = MyViewModel()
    
    var body: some View {
        VStack {
            Text(viewModel.text)
            Button("ボタン") {
                self.viewModel.text = "Goodnight, World"
            }
        }
    }
}

データをTextFieldと紐付ける事もできます。 TextFieldの引数はBinding<String>なので$viewModel.textとドルを付けてBindingオブジェクトに変えて上げる必要があります。

class MyViewModel : ObservableObject, Identifiable {
    @Published
    var text: String = "Hello, World"
}

struct ContentView: View {
    @ObservedObject var viewModel = MyViewModel()
    
    var body: some View {
        VStack {
            Text(viewModel.text)
            TextField("Placeholder", text: $viewModel.text)
        }
    }
}

f:id:llcc:20191201190104p:plain

画面遷移はNavigationViewを使うと実現できます。

struct ContentView: View {
    var body: some View {
        NavigationView {
            NavigationLink(destination: DestinationView()) {
                Text("ボタン")
            }
        }
    }
}

struct DestinationView: View {
    var body: some View {
        Text("遷移先")
    }
}