LoginSignup
1
2

More than 3 years have passed since last update.

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

Posted at

はじめに

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

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

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

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

参考記事
【SwiftUI】Firebaseからデータを読み取り、ListViewのRowを更新する

開発環境

OSX 10.15.7 (Catalina)
Xcode 12.2.0
CocoaPods 1.10.0

Like機能の実装

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

実装方法

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

タップ後
ContentView_swift_—_Edited.png

コード全体

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

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)
    }
}

追記

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

nw_protocol_get_quic_image_block_invoke dlopen libquic failed

参考文献
Strange error nw_protocol_get_quic_image_block_invoke dlopen libquic failed
Swift Firebase Connection

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