100DaysOfSwiftUI Day60 Challengeをやってみる (Step4 : Friendへのジャンプ機能実装)

UserのDetailViewの実装はできたので、こんどは、Friendの行をクリックして、FriendのUserDetailViewへ飛ぶようにしてみます。

実装概要

クリックされた時に、そのFriendを探して、そのUserのDetailViewに飛びます。

User1のFriendのUser2をクリックされたとすると、画面はRoot>User1Detail>User2Dtailという形でスタックしている形になります。

該当Userの検索

UserのDetailViewはすでにあるので、再利用できます。
実装が必要となるのは、クリックされた時に、Friendの情報から、該当するUserを見つけて、新しいUserDetailViewを作るところです。

まずは、NavigationLinkの実装

まずは、クリックすることで、UserDetailViewへジャンプするようにしましょう。

該当するユーザーの検索は後で実装したいので、同じユーザーを設定して別のDetailViewを表示してみましょう。

struct UserDetailView: View {
    var user:User
    var body: some View {
        VStack(alignment: .leading) {
            Section(header: Text("General")) {
                Text("ID : \(user.id)")
                    .font(.footnote)
                Text("Name : \(user.name)")
                Text("age  : \(user.age)")
                Text("company  : \(user.company)")
            }
            Section(header: Text("Tag")) {
                List(user.tags) { tag in
                    Text("\(tag.name)")
                }
            }
            Section(header: Text("Friend")) {
                List(user.friends) { friend in
                    NavigationLink(destination: UserDetailView(user: self.user) ) { // <- clickした行と無関係に入れてます
                        Text("FriendName: \(friend.name)")
                    }
                }
            }

        }
    .navigationBarTitle("User Detail:")
    }
}

動かしてみると期待通りに動きます。

FriendのUser情報検索はどこに実装する?

まず、全体のUserListが必要なことは自明ですので、足してしまいましょう。

機能的には何も変わりませんが、色々とエラーがでるので、修正しました。
# UserListのinitializerに1つのuserを受け取るものを作りました。

struct UserDetailView: View {
    var userList: UserList
    var user:User
    var body: some View {
        VStack(alignment: .leading) {
            Section(header: Text("General")) {
                Text("ID : \(user.id)")
                    .font(.footnote)
                Text("Name : \(user.name)")
                Text("age  : \(user.age)")
                Text("company  : \(user.company)")
            }
            Section(header: Text("Tag")) {
                List(user.tags) { tag in
                    Text("\(tag.name)")
                }
            }
            Section(header: Text("Friend")) {
                List(user.friends) { friend in
                    NavigationLink(destination: UserDetailView(userList: self.userList,
                                                               user: self.user) ) {
                        Text("FriendName: \(friend.name)")
                    }
                }
            }

        }
    .navigationBarTitle("User Detail:")
    }
}

struct UserDetailView_Previews: PreviewProvider {
    static var user = User(id: "Super Guitarist", isActive: false, name: "Michael Hedges", age: 34)
    static var userList = UserList(user: user)
    static var previews: some View {
        UserDetailView(userList: userList, user: user)
                       
    }
}

ユーザー検索は、Friendに保持しているidを使って、UserListで検索することにしました。

検索をUserListで行うことで、NavigationLinkの引数内で実装

もう少し工夫して、見つからない人はNavigationLinkにしないことにしてみました。

struct UserDetailView: View {
    var userList: UserList
    var user:User
    var body: some View {
        VStack(alignment: .leading) {
            Section(header: Text("General")) {
                Text("ID : \(user.id)")
                    .font(.footnote)
                Text("Name : \(user.name)")
                Text("age  : \(user.age)")
                Text("company  : \(user.company)")
            }
            Section(header: Text("Tag")) {
                List(user.tags) { tag in
                    Text("\(tag.name)")
                }
            }
            Section(header: Text("Friend")) {
                List(user.friends) { friend in
                    if self.userList.findUserFromFriend(friend: friend) != nil {
                        NavigationLink(destination: UserDetailView(userList: self.userList,
                                                                   user: self.userList.findUserFromFriend(friend: friend)!) ) {
                            Text("FriendName: \(friend.name)")
                        }
                    } else {
                        Text("FriendName: \(friend.name)")
                    }
                }
            }

        }
    .navigationBarTitle("User Detail:")
    }
}

ちなみに、Friendに該当するUserを検索するコードは、次の1行です(UserList内に定義してます。)

func findUserFromFriend(friend: Friend) -> User? {
    return users.first(where: {$0.id == friend.id})
}

これで、Challengeは終わり。

SwiftUIを使って作る時に気をつけると良いこと
  • レイアウトを検討したければ、常にPreviewを使えるようにした方がよい
  • でも、Previewではデバッグできないので気をつける
  • いきなり大きな部品を作るのではなく、小さい部品を作って組み合わせる

最後のものは、一般に言われていることですが、SwiftUIでは、UIの部品化がより行いやすくなっていると思うので、強く意識してコードを書くと幸せになれると思います。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です