트위터 클론 코딩 & Firebase 사용
가볍게 봐주시면 감사합니다 😁
Tweet 피드 중 기존 "좋아요" 데이터 불러오기
이슈 ▾
- 기존에 좋아요를 눌렀던 피드가 앱을 재접속하여 다시 누르면 또 다시 좋아요가 카운팅된다.
- 사용자가 좋아요를 눌렀는지에 대한 여부를 체크하여 View가 보여질 때 데이터도 함께 동기화가 되어야 한다.
원인 ▾
- Tweet - Model
struct Tweet {
let caption: String
let tweetID: String
let uid: String
var likes: Int
var timestamp: Date!
let retweetCount: Int
var user: User
var didLike = false // 이 부분
// ...
}
- 기존 좋아요를 판별하기 위한 Bool 타입 didLike가 false로 초기화가 되기 때문에, 좋아요를 누른 뒤 앱을 재접속하면 true여야 되는 값도 false로 되어 있게 된다.
해결 ▾
- 내가 원하는 것
- Tweet(Model)으로 피드를 업데이트하고, 업데이트 된 피드(데이터)를 기반으로 사용자가 트윗을 좋아했는지 확인하기
- 만약, UI를 업데이트하기 전에 사용자가 트윗을 좋아요를 누르면, 작업이 더 오래 걸리고, DB에서 많은 불필요한 작업 수행
- 사용자가 해당 트윗을 좋아하면 사용자 인터페이스 업데이트 하기
- 모든 항목을 확인하면 데이터 소스를 업데이트 하기
- Tweet(Model)으로 피드를 업데이트하고, 업데이트 된 피드(데이터)를 기반으로 사용자가 트윗을 좋아했는지 확인하기
- TweetService - API
/// 트윗 좋아요 눌렀는지 체크하는 API
func checkIfUserLikedTweet(_ tweet: Tweet, completion: @escaping(Bool) -> Void) {
guard let uid = Auth.auth().currentUser?.uid else { return }
REF_USER_LIKES.child(uid).child(tweet.tweetID).observeSingleEvent(of: .value) { snapshot in
completion(snapshot.exists())
}
}
- 현재 사용자의 ID를 가져오고, 해당 ID를 가지고 DB에 좋아요 누른부분이 존재하는지 체크한다.
- observeSingleEvent ▾
- snapshot
- 하위 데이터를 포함하여 해당 위치의 모든 데이터를 포함하는 snapshot이 이벤트 콜백에 전달됨
- exsits() ▾
- 해석하면, "DataSnapshot에 null이 아닌 값이 포함되면 yes를 반환합니다." 라고 한다.
- 즉, 데이터가 null이 아니면 true값이 반환된다고 보면 된다.
- FeedController - Controller
/// 트윗 데이터 불러오기
func fetchTweets() {
TweetService.shared.feetchTwetts { tweets in
self.tweets = tweets
self.checkIfUserLikedTweets(self.tweets)
}
}
/// 트윗 좋아요 데이터 불러오기
func checkIfUserLikedTweets(_ tweets: [Tweet]) {
for (index, tweet) in tweets.enumerated() {
TweetService.shared.checkIfUserLikedTweet(tweet) { didLike in
guard didLike == true else { return }
self.tweets[index].didLike = true
}
}
}
- checkIfUserLikedTweets(_ tweets: [Tweet])
- tweets.enumerated()
-
-
- "(n, x)의 시퀀스를 반환하는데, 여기서 n은 0에서 시작하는 연속적인 정수를 나타내고, x는 시퀀스의 요소를 나타낸다."
- 즉, tweets의 데이터를 해당 index에 맞는 tweet을 하나하나 순회한다고 보면 된다.
- gurad didLike == true else { return }
- didLike가 true값이 아니면 return
- true값이면 tweets의 해당 index에 didLike의 값을 true로 변경
-
- tweets의 didLike가 true값으로 변경이 되면 didSet을 이용하여 collectionView를 새로고침 해준다.
private var tweets = [Tweet]() {
didSet { collectionView.reloadData() }
}
- reloadData()가 호출이 되면 자연스럽게 cellForItemAt이 호출이 된다.
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! TweetCell
cell.delegate = self
cell.tweet = self.tweets[indexPath.row]
return cell
}
- 이렇게 되면, cell은 다시 tweet 데이터를 가지고 UI를 업데이트 하게 되는 것이다.
- TweetCell - View
// TweetCell (View)
var tweet: Tweet? {
didSet { configureUI() }
}
func configureUI() {
guard let tweet = tweet else { return }
let viewModel = TweetViewModel(tweet: tweet)
captionLabel.text = tweet.caption
profileImageView.sd_setImage(with: viewModel.profileImageUrl)
infoLabel.attributedText = viewModel.userInfoText
likeButton.tintColor = viewModel.likeButtonTintColor
likeButton.setImage(viewModel.likeButtonImage, for: .normal)
}
- TweetCell의 데이터도 역시 변하게 되면서 configureUI() 메서드가 호출이 되고, 해당 viewModel을 통해 view에 관련 데이터가 가공이 되는 것이다.
'Udemy.zip' 카테고리의 다른 글
[Swift]RxSwift 기초 문법 (0) | 2022.04.13 |
---|---|
[Swift] Firebase 기능 (0) | 2022.03.25 |
[Swift]Table View 이슈 (0) | 2022.03.05 |
[Swift]ActionSheet-Protocol (0) | 2022.02.25 |