2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AndroidエンジニアがSwiftUIをやってみてわからんかったこと3選

Posted at

この記事で伝えたいこと

普段Androidエンジニアをやっている私がSwiftUIに挑戦してみて、理解するのに時間がかかった、あるいはまだ理解できていないことをつらつら書いていきます。
Swift自体ちゃんとやったことがないので、そこからわからないことが多かったです。

SwiftUIをやってみた経緯

KMP(Kotlin Multiplatform)やCMP(Compose Multiplatform)、Flutterといったクロスプラットフォームに興味を持っていたので、まずはKMP+SwiftUIという構成でiOSアプリを作ってみることにしました。
CMPを選ばなかったのは、まずはSwiftUIを使ってみてJetpack Composeとの違いを感じてみたかったからです。

まだSwiftUIのチュートリアルしかやっていないので、今回の記事ではKMPには触れません。
それにしても、昨今のクロスプラットフォームは選択肢が多くて迷いますよね。

すぐに理解できなかったものたち

まずはコードの全体像から

Landmarks.swift
struct LandmarkList: View {
    @Environment(ModelData.self) var modelData
    @State private var showFavoritesOnly = false
    
    var filteredLandmarks: [Landmark] {
        modelData.landmarks.filter { landmark in
            (!showFavoritesOnly || landmark.isFavorite)
        }
    }
    
    var body: some View {
        NavigationSplitView {
            List {
                Toggle(isOn: $showFavoritesOnly) {
                    Text("Favorites only")
                }
                
                ForEach(filteredLandmarks) { landmark in
                    NavigationLink {
                        LandmarkDetail(landmark: landmark)
                    } label: {
                        LandmarkRow(landmark: landmark)
                    }
                }
            }
            .animation(.default, value: filteredLandmarks)
            .navigationTitle("Landmarks")
        } detail: {
            Text("Select a Landmark")
        }
    }
}

struct(構造体)

struct.swift
struct LandmarkList: View {

SwiftUIでは、Viewに準拠したstructを使うことでUIを構築します。
そこまではわかりやすいのですが、他でも多々使われているようで。

Landmark.swift
struct Landmark: Hashable, Codable, Identifiable {
    var id: Int
    var name: String
    var park: String
    var state: String
    var description: String
    var isFavorite: Bool

    
    private var imageName: String
    var image: Image {
        Image(imageName)
    }
    
    private var coordinates: Coordinates
    var locationCoordinate: CLLocationCoordinate2D {
           CLLocationCoordinate2D(
               latitude: coordinates.latitude,
               longitude: coordinates.longitude)
       }
    
    struct Coordinates: Hashable, Codable {
        var latitude: Double
        var longitude: Double
    }
}

こんな感じで使われているのですが、Kotlinには構造体がないので、どういった目的で使われてるのか最初はピンときませんでした。

調べてみて、値渡し(copy)をできたり、継承できないといった特徴がわかり、Kotlinでいうところのdata classに近いものと理解しました。

ひとまとまりのデータを表現するのにはstructを使っておくのが良さそうです。

@State

State.swift
@State private var showFavoritesOnly = false

値の更新を監視するためのもの。これを使わないとstruct内でプロパティを変更することができないので、値が変わった時の再描画もできない

Kotlin(Compose)で言うところのmutableStateFlowあたりが近いかなと思いました。

@environment

Environment.swift
@State private var showFavoritesOnly = false

これが一番わからなかったです。最初は環境変数やグローバル変数みたいな話なのかと思っていましたが、そうでもないようで。

どうやら、親ビューから暗黙的に値を注入できるようになるみたいで、DIコンテナのような役割を果たすようです。

DIコンテナは値の扱いを楽にしますが、暗黙的に行なってしまうことから、データの流れを追いにくくなる気がしますね。

特に初学者は理解が必要な部分だと感じました。

おわりに

「これはKotlinにおける〜」って考え方で一つずつ調べていけば、概念的にはそんなに難しくないことが多かったです。

全然関係ないですが、Android Studioのショートカットに慣れすぎたせいで
Xcodeの操作が辛いです。

2
0
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?