はじめに
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()
}
}
コード全体
今回機能の実装にあたり、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