LoginSignup
0
4

More than 3 years have passed since last update.

【Xcode12.3】Appleプラットフォームのアプリ開発入門〜オブジェクト編〜【SwiftUI】

Last updated at Posted at 2021-01-08

SwiftUI とは

SwiftUIとは、AppleプラットフォームのアプリケーションUIを、開発言語をSwiftとした宣言型シンタックス(Declarative Syntax)で構築するUIフレームワークです。

SwiftUI同様、Apple製品のアプリケーションUIを構築するフレームワークとしてはFlutterが有名ですが、その違いを以下の表にまとめました。

SwiftUI Flutter
対応プラットフォーム Appleのみ iOS, Android, Web
IDE Xcode Android Studio, VS code
記述形式 宣言的シンタックス 宣言的シンタックス
開発言語 Swift Dart, Widget
コード量 少ない 多い
拡張性 Flutterに劣る 高い

Appleプラットフォームのアプリ開発にあたって、Apple公式のフレームワークSwiftUIに注目していきます。

SwiftUI

テキスト

テキスト(Text)

スクリーンショット 2021-01-13 15.12.32.png

テキスト
Text("<文字列>")

リンク(Link)

スクリーンショット 2021-01-09 13.25.55.png

リンク
Link(destination: <URL>) { Text("<ラベル>") }

テキストフィールド(Text Field)&セキュアテキストフィールド(Secure Field)

スクリーンショット 2021-01-13 12.28.32.png
↑未入力の状態(プレースホルダテキストが表示)

スクリーンショット 2021-01-13 15.39.24.png

↑テキストフィールド。入力中の状態

スクリーンショット 2021-01-13 12.14.25.png
↑セキュアテキストフィールド。入力中の状態

テキストフィールドとセキュアテキストフィールド
@State private var value: String = ""

// TextFieldとSecureFieldの値を同一プロパティにすることで連動が可能
TextField("<プレースホルダテキスト>", text: $value)
SecureField("<プレースホルダテキスト>", text: $value)

テキストエディタ

スクリーンショット 2021-01-13 15.33.58.png

テキストエディタ
@State private var value: String = ""

TextEditor(text: $value)  // テキストエディタはプレースホルダテキストを標準で実装していない

ボタン

システムボタン(Button)

スクリーンショット 2021-01-08 19.17.40.png

ボタン
Button(action: <実行メソッド>) { <ラベル> }

エディタボタン

スクリーンショット 2021-01-08 19.51.43.png
↑エディタが非アクティブな状態

スクリーンショット 2021-01-08 19.53.10.png
↑エディタがアクティブな状態

エディタボタン
EditButton()

スイッチ(Toggle Button)

スクリーンショット 2021-01-13 15.42.33.png

スイッチ
@State private var flg: Bool = True

Toggle(isOn: $flg) {
    <ラベル>
}

サインインボタン(Sign In With Apple Button)

スクリーンショット 2021-01-13 14.22.30.png

サインインボタン
import Authentication Services  // ASAuthorizationAppleIDButtonの実装に必要なパッケージ

struct SignInWithAppleButton: UIViewRepresentable {
    func makeUIView(context: Context) -> ASAuthorizationAppleIDButton {
    // ASAuthorizationAppleIDButtonはApple標準のボタンコンポーネントだが、
    // SwiftUIの標準コンポーネントとして用意されていないため、SwiftUIのViewコンポーネントとして実装する必要がある
        let button = ASAuthorizationAppleIDButton()
        return button
    }

    func updateUIView(_: ASAuthorizationAppleIDButton, context _: Context) [}
}

SignInWithAppleButton()

認証機能を実装したい場合は、こちらを参照。

ピッカー

ピッカ-(Picker)

スクリーンショット 2021-01-13 11.30.57.png

ピッカ-
Picker(selection: .<選択値プロパティ名>, label: Text(<ラベル>)) {
    Text(<ラベル>).tag(<選択値>)
}

カラーピッカー(Color Picker)

スクリーンショット 2021-01-08 19.32.30.png

カラーピッカー
ColorPicker("<ラベル>", selection: .constant(.<既定色>))

日付ピッカー(Date Picker)

スクリーンショット 2021-01-08 19.37.47.png

日付ピッカー
DatePicker(selection: .constant(Date()), label: { Text("<ラベル>") })

リスト

リスト(List)

スクリーンショット 2021-01-09 13.34.39.png

リスト
List { <コンテンツ> }

ラベル(Label)

スクリーンショット 2021-01-09 13.22.14.png

ラベル
Label("<ラベル>", systemImage: "<記号>")

セクション(Section)

スクリーンショット 2021-01-13 12.11.59.png

セクション
Section(header: Text(<ラベル>)) {
    <コンテンツ>
}

グループ(Disclosure Group)

スクリーンショット 2021-01-08 19.43.42.png
↑閉じた状態

スクリーンショット 2021-01-08 19.44.11.png
↑開いた状態

アウトライン(Outline Group)

スクリーンショット 2021-01-09 17.01.28.png
↑ListなしVer.

スクリーンショット 2021-01-09 17.02.36.png
↑ListありVer.

アウトライン(実装が難解だったため、ソースコードを記述)
struct CityData: Identifiable {  // OutlineGroupで使用するデータはIdentifiableプロトコルに適合していなければならない
    //構造体"CityData"のプロパティはid, name, sitesの3つ
    let id = UUID()  //UUID(ユニークID)…128bitの16進数
    let name: String
    var sites: [CityData]?  // タイプメソッドresult()によって値が後から代入される

    static func result() -> [CityData] {  // タイプメソッド(静的メソッド)の定義はstaticキーワードを付加
        let city1 = [CityData(name: "Site A"), CityData(name: "Site B")]
        let city2 = [CityData(name: "Site C"), CityData(name: "Site D")]

        return [CityData(name: "city1", sites: city1),
                CityData(name: "city1", sites: city1)]
    }  // タイプメソッドによってsitesの値が以下のようになる
       // [name: city1, sites: Optional([name: site A, sites: nil], [name: Site B, sites: nil]) 
       //  name: city2, sites: Optional([name: site C, sites: nil], [name: Site D, sites: nil])]
}

struct ContentView: View {
    var body: some View {
        List {
            ForEach(CityData.result()) { city in  // CityData.sitesのname: city1, city2のそれぞれに対して以下の処理を実行
                OutlineGroup(city, children: \.sites) { site in  // CityData.sites.sitesのname: site A, site Bのそれぞれに対して以下の処理を実行
                    Text(site.name)
                }
            }
        }
    }
}
Identifiableプロトコル
public protocol Identifiable {
    associatedtype ID: Hashable  //型パラメータ(=プレースホルダ)"ID"は"Hashable"プロトコルに適合
    var id: Self.ID { get }  //プロパティ"id"は読み取り専用であり、インスタンス自身の型パラメータ"ID"に適合
}
Hashableプロトコル
public protocol Hashable{
    func hash(into hasher: inout Hasher)
    var hashValue: Int { get }  

グループボックス(Group Box)

スクリーンショット 2021-01-09 13.19.20.png

グループボックス
GroupBox(label: <ラベル>) { <コンテンツ> }
グループ
DisclosureGroup("<ラベル>") { <コンテンツ> }

フォーム(Form)

スクリーンショット 2021-01-09 13.14.02.png

フォーム
Form { <コンテンツ> }

ビュー

ナビゲーションビュー(Navigation View), ナビゲーションリンク(Navigation Link)

Simulator Screen Shot - iPhone 12 - 2021-01-09 at 13.57.48.png
↑画面遷移前

Simulator Screen Shot - iPhone 12 - 2021-01-09 at 13.57.51.png
↑画面遷移後

ナビゲーションリンク
NavigationView {  //NavigationLinkはNavigationViewのスコープ内で記述
    NavigationLink(destination: <Viewプロトコルに準拠したインスタンス>) { <ラベル> }
}

進捗ビュー(Progress View)

スクリーンショット 2021-01-13 11.41.56.png

進捗ビュー
ProgressView(value: <0~1の進捗値>)

スクロールビュー(Scroll View)

スクリーンショット 2021-01-13 11.58.12.png

スクロールビュー
ScrollView(.<方向>) {
    VStack {   // 縦方向の場合はVStackでまとめる
        <コンテンツ>
    }
    .frame(maxWidth: .infinity)  // 対象範囲の最大化
}

スライダ(Slider)&ステッパ(Stepper)

スクリーンショット 2021-01-13 14.36.19.png
↑スライダ

スクリーンショット 2021-01-13 14.38.12.png
↑ステッパ

スライダとステッパ
@State private var value: Double = 0

// SliderとStepperの値を同一プロパティにすることで連動が可能
Slider(value: $value, in: 0...100)
Stepper(value: $value, in: 0...100) {
    <ラベル>
}

タブバー(Tab View)

スクリーンショット 2021-01-13 14.46.24.png

タブバー
@State private var selection = 0 // 選択タブを保持するプロパティ

TabView(selection: $selection) {
    Text("<コンテンツ>").tabItem { Text(<ラベル>) }.tag(0)
    Text("<コンテンツ>").tabItem { Text(<ラベル>) }.tag(1)
}
0
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
4