UserのDetailViewの実装はできたので、こんどは、Friendの行をクリックして、FriendのUserDetailViewへ飛ぶようにしてみます。
実装概要
クリックされた時に、そのFriendを探して、そのUserのDetailViewに飛びます。
User1のFriendのUser2をクリックされたとすると、画面はRoot>User1Detail>User2Dtailという形でスタックしている形になります。
該当Userの検索
UserのDetailViewはすでにあるので、再利用できます。
実装が必要となるのは、クリックされた時に、Friendの情報から、該当するUserを見つけて、新しいUserDetailViewを作るところです。
まずは、クリックすることで、UserDetailViewへジャンプするようにしましょう。
該当するユーザーの検索は後で実装したいので、同じユーザーを設定して別のDetailViewを表示してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
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を受け取るものを作りました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
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で検索することにしました。
もう少し工夫して、見つからない人はNavigationLinkにしないことにしてみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
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内に定義してます。)
1 2 3 |
func findUserFromFriend(friend: Friend) -> User? { return users.first(where: {$0.id == friend.id}) } |
これで、Challengeは終わり。
- レイアウトを検討したければ、常にPreviewを使えるようにした方がよい
- でも、Previewではデバッグできないので気をつける
- いきなり大きな部品を作るのではなく、小さい部品を作って組み合わせる
最後のものは、一般に言われていることですが、SwiftUIでは、UIの部品化がより行いやすくなっていると思うので、強く意識してコードを書くと幸せになれると思います。
Sponsor Link