본문 바로가기

프로젝트/Twitter Clone App (w∕Firebase)

22. 버그수정 #2

버그수정 #2
fetchTweets의 정렬 문제, SideMenu의 배경색 문제


fetchTweets의 정렬 문제

지금도 Tweet들을 Firebase에서 가져오는 데에는 문제가 없지만, 사소하지만 대단히 중요한 문제가 하나 있다.

바로 Tweet이 글을 작성한 순서대로 표시되지 않는다는 점이다.
해당 문제를 해결하기 위해 두 가지 접근법을 사용한다.

fetchTweets의 정렬 문제
| FeedView의 경우, Firebase order

Firestore.firestore().collection("tweets").order(by: "timestamp", descending: true).getDocuments { snapshot, _ in
    guard let documents = snapshot?.documents else {
        return
    }

    let tweets = documents.compactMap({
        try? $0.data(as: Tweet.self)
    })
    completion(tweets)
}

FeedView는 계정에 상관 없이 DB의 모든 Tweet을 순서대로 보여주는 역할을 한다.
이때는 간단히 Firestore의 order 메서드를 추가하고, 파라미터로 기준 데이터와 정렬 방식을 전달하면 된다.

fetchTweets의 정렬 문제
| ProfileView의 경우, sorted

func fetchTweets(foruid uid: String, completion: @escaping([Tweet]) -> Void) {
    Firestore.firestore().collection("tweets").whereField("uid", isEqualTo: uid).getDocuments { snapshot, _ in
        guard let documents = snapshot?.documents else {
            return
        }

        let tweets = documents.compactMap({
            try? $0.data(as: Tweet.self)
        })
        completion(tweets)
    }
}

ProfileView에서 호출하는 fetchTweets(foruid:) 메서드의 경우 getDocuments 가 호출되기 전
whereField를 호출해 원하는 uid에 해당하는 데이터를 가져오도록 구현돼 있다.
문제는 whereField와 order는 중첩돼 사용할 수 없다는 부분인데,
둘을 모두 사용하기 위해서는 DB에서 어떤 것을 우선적으로 처리해 반환할 것인지를 결정하고,
나머지 후처리를 앱에서 직접 처리해야 한다.

func fetchTweets(foruid uid: String, completion: @escaping([Tweet]) -> Void) {
    Firestore.firestore().collection("tweets").whereField("uid", isEqualTo: uid).getDocuments { snapshot, _ in
        guard let documents = snapshot?.documents else {
            return
        }

        let tweets = documents.compactMap({
            try? $0.data(as: Tweet.self)
        })
        completion(tweets.sorted(by: { $0.timestamp.dateValue() > $1.timestamp.dateValue() }))
    }
}

아무래도 정렬된 전체 Tweet을 받아와 앱에서 특정 사용자에 대한 Tweet을 걸러 내는 것보다는
특정 사용자에 대한 Tweet을 받아온 뒤 앱에서 정렬을 하는 쪽이 어떤 면에서든 바람직하기 때문에 정렬을 따로 구현했다.

이제는 FeedView와 ProfileView에서 Tweet을 정렬된 형태로 보여준다.

SideMenu의 배경색 문제
| SideMenuView

기본적으로 LightMode를 기준으로 디자인을 시작하기도 했고, DarkMode를 완전히 지원하지는 않는다.
다만 Simulator에서 변하는 경우 불편함이 있어 SideMenu의 배경색을 Scheme에 따라 변하도록 변경했다.

더보기

Source

import SwiftUI
import Kingfisher

struct SideMenuView: View {
    @EnvironmentObject var authViewModel: AuthViewModel

    var body: some View {
        if let user = authViewModel.currentUser {
            VStack(alignment: .leading, spacing: 32) {
                VStack(alignment: .leading) {
                    KFImage(URL(string: user.profileImageUrl))
                        .resizable()
                        .scaledToFill()
                        .clipShape(Circle())
                        .frame(width: 48, height: 48)

                    VStack(alignment: .leading, spacing: 4) {
                        Text(user.fullname)
                            .font(.headline)

                        Text("@\(user.username)")
                            .font(.caption)
                            .foregroundColor(.gray)
                    }

                    UserStatsView()
                        .padding(.vertical)
                }
                .padding(.leading)

                ForEach(SideMenuViewModel.allCases, id: \.rawValue) { viewModel in
                    if viewModel == .profile {
                        NavigationLink(destination: ProfileView(user: user)) {
                            SideMenuRowView(viewModel: viewModel)
                        }
                    } else if viewModel == .logout {
                        Button {
                            authViewModel.signOut()
                        } label: {
                            SideMenuRowView(viewModel: viewModel)
                        }
                    } else {
                        SideMenuRowView(viewModel: viewModel)
                    }
                }

                Spacer()
            }
            .background(Color(UIColor.systemBackground))
        }
    }
}
        VStack(alignment: .leading, spacing: 32) {
                    .
                    .
                    .
                    } else {
                        SideMenuRowView(viewModel: viewModel)
                    }
                }

                Spacer()
            }
            .background(Color(UIColor.systemBackground))
        }
    }
}

SideMenu를 구성하는 ParentView인 VStack의 background를 systemBackground로 지정했다.

'프로젝트 > Twitter Clone App (w∕Firebase)' 카테고리의 다른 글

24. 기능 구현 #10  (0) 2023.01.20
23. 기능 구현 #9  (0) 2023.01.20
21. DB와 연결하기 #3  (0) 2023.01.18
20. 기능 구현 #8  (0) 2023.01.17
19. 기능 구현 #7  (0) 2023.01.14