【SwiftUI】Likeボタンとリスト内セルにボタンを実装する場合の注意点

# はじめに
SwiftUIでFirebaseからデータを読み取り、これまで作成したカード内容を更新することを目的とする。

今回はカード内のLikeボタンの実装を行います。

結論を最初に言うと、ListView内でButtonを実装する場合はそれぞれのImageに```.onTapGesture```を設定する必要があります。
その点がわかっていなかったため、実装に時間がかかってしまいました。

前回までの記事は以下を参考ください。

**参考記事**
[【SwiftUI】Firebaseからデータを読み取り、ListViewのRowを更新する](https://qiita.com/m37335/items/76673ebe302192711595)

# 開発環境
OSX 10.15.7 (Catalina) 
Xcode 12.2.0
CocoaPods 1.10.0

# Like機能の実装
ボタンの設定に時間がかかってしまったため、FirebaseのLike数の更新機能の実装までは至りませんでした。
今回はタップした際にハートの色を変更する機能のみ実装します。
設定のみしたaction機能は次回以降に実装します。

##実装方法

```swift
struct ContentView: View {
    
    @State private var isLiked = false
    
    var body: some View {
        VStack {
            Text(isLiked ? "Liked!" : "unLiked!")
            HeartButton(isLiked: $isLiked)
        }
    }
}

struct HeartButton: View {
    @Binding var isLiked : Bool
    
    
    var body: some View {
        Button(action: {
            self.isLiked.toggle()
        }, label: {
            Image(systemName: isLiked ? "heart.fill": "heart")
                .font(.largeTitle)
                .foregroundColor(Color.red)
                .frame(width: 100, height: 100)
        })
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

```

**タップ前**
![ContentView_swift_—_Edited.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/867981/3d66b76a-d73a-4e27-9461-81bcaaf381d0.png)


**タップ後**
![ContentView_swift_—_Edited.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/867981/1bffd10b-38dd-393b-96f7-4a1b8189ed9d.png)


## コード全体
今回機能の実装にあたり、View内のコードを見直し、修正しました。
上記のコードを参考に、List内のカードに実装します。
List内にButtonを実装する場合は、実装した場合はセル全体が選択可能になってしまい、特定のボタンのみを選択することができません。
そのため、ボタンの代わりにtextやimageに```.onTapGesture```を実装する必要があります。
現在は色が変わるだけしか実装できていません。
今後はタップした場合にFirebaseを更新し、Like数が増減できるようにする予定です。

```swift
struct ContentRowView: View {
    var id  = ""
    var user = ""
    var userImage = ""
    var haiku = ""
    var mapImage = ""
    var place = ""
    var likes = ""
    // ○秒、○日、○年前を表示
    
    var createdDate = ""

    static let formatter = RelativeDateTimeFormatter()
    
    // 以下を追記
    @State var isLiked = false
    
    var body: some View {
        
        ContentRowView.formatter.locale = Locale(identifier: "ja_JP")
        
        let fmt = ISO8601DateFormatter()
        let date1 = fmt.date(from: createdDate)!
        let components = Calendar.current.dateComponents(
            [.day, .year, .month, .minute, .second],
            from: Date(),
            to: date1
        )
        let timeAgo = ContentRowView.formatter.localizedString(from: components)
        
        return VStack {
            // mapImage
            VStack {
                AnimatedImage(url: URL(string: mapImage)!)
                    .resizable()
                    //.aspectRatio(contentMode: .fit)
                    .cornerRadius(12.0, antialiased: /*@START_MENU_TOKEN@*/true/*@END_MENU_TOKEN@*/)
                HStack {
                    Spacer()
                    Text(place).font(.caption).foregroundColor(.gray)
                        .padding(.bottom, 5)
                }
            }
            // Haiku
            Text(haiku).font(.title3).fontWeight(.bold)
            // Likes Number
            HStack {
                Image(systemName: "heart").font(.headline).foregroundColor(Color("pinkColor"))
                Text(likes).font(.headline).foregroundColor(Color("pinkColor"))
                Spacer()
            }.padding(.top, 5)
            // Info
            HStack {
                AnimatedImage(url: URL(string: userImage)!)
                    .resizable()
                    .frame(width: 30, height: 30)
                    .clipShape(Circle())
                
                Text(user).font(.headline).fontWeight(.light)
                + Text("・").font(.headline).fontWeight(.light)
                + Text(timeAgo).font(.headline).fontWeight(.light)
                Spacer()
                    // If Comment Button was push, it call CommentView.
                Image(systemName: "text.bubble")
                    .font(.title)
                    .foregroundColor(.gray)
                    .onTapGesture {
                        print("Button Tapped")
                    }
                    .frame(width: 30, height: 30)
                
                // Like Button push Image to add like's Number.
                Image(systemName: isLiked ? "heart.fill": "heart")
                    .font(.title)
                    .foregroundColor(Color("pinkColor"))
                    .onTapGesture {
                        self.isLiked.toggle()
                    }
                    .frame(width: 30, height: 30)
            }.padding(5)
        }.padding(.top, 8).frame(height: 391)
    }
}

```

# 追記
**エラー**
下記のエラーを確認して、修正しようとしましたが、現状では解決できないエラーのようです。
無視しても致命的にはならない現象のため、いったんそのままにします。

```terminal
nw_protocol_get_quic_image_block_invoke dlopen libquic failed

```

**参考文献**
[Strange error nw_protocol_get_quic_image_block_invoke dlopen libquic failed
](https://stackoverflow.com/questions/64029844/strange-error-nw-protocol-get-quic-image-block-invoke-dlopen-libquic-failed)[Swift Firebase Connection](https://forums.swift.org/t/swift-firebase-connection/41632/4)