🟨 구현 화면


🟨 구현 순서
1️⃣ TwitterUser 정보 관련 데이터 모델 생성
import Foundation
import Firebase
struct TwitterUser: Codable {
let id: String
var displayName: String = ""
var username: String = ""
var followersCount: Int = 0
var followingCount: Int = 0
var createdOn: Date = Date()
var bio: String = ""
var avatarPath: String = ""
var isUserOnboarded: Bool = false
init(from user: User) {
self.id = user.uid
}
}
2️⃣ Networking 폴더 내에 DatabaseManager 파일 생성
- 데이터 베이스 접근 및 관리 목적
- collectionUsers(add user: User) 메서드
- 데이터 베이스 내에 계정 정보를 등록하게 되면 오토 id가 생성된다.
- 이를 통해 계정에 대한 정보를 설정할 수 있도록 하는 함수이다.
- collectionUsers(retreive id: String) 메서드
- 데이터 베이스 내에 저장된 계정 정보의 id를 통해 접근할 수 있도록 해주는 메서드이다.
import Foundation
import Firebase
import FirebaseFirestoreSwift
import FirebaseFirestoreCombineSwift
import Combine
class DatabaseManager {
static let shared = DatabaseManager()
let db = Firestore.firestore()
let usersPath: String = "users"
let tweetsPath: String = "tweets"
func collectionUsers(add user: User) -> AnyPublisher<Bool, Error> {
let twitterUser = TwitterUser(from: user)
return db.collection(usersPath).document(twitterUser.id).setData(from: twitterUser)
.map { _ in return true }
.eraseToAnyPublisher()
}
func collectionUsers(retreive id: String) -> AnyPublisher<TwitterUser, Error> {
db.collection(usersPath).document(id).getDocument()
.tryMap { try $0.data(as: TwitterUser.self) }
.eraseToAnyPublisher()
}
3️⃣ ViewModels 폴더 내에 AuthenticationViewViewModel 파일 수정
- 계정을 등록하기 전에 해당 계정에 대한 정보를 입력하기 위함
- createUser() 메서드가 동작할 때 계정에 대한 정보 (TwitterUser) 라는 걸 설정한다.
final class AuthenticationViewViewModel: ObservableObject {
@Published var email: String?
@Published var password: String?
@Published var isAuthenticationFormValid: Bool = false
@Published var user: User?
@Published var error: String?
private var subscriptions: Set<AnyCancellable> = []
...
func createUser() {
guard let email = email,
let password = password else { return }
AuthManager.shared.registerUser(with: email, password: password)
// handleEvents?
.handleEvents(receiveSubscription: { [weak self] user in
self?.user = user as? User
})
.sink { [weak self] completion in
if case .failure(let error) = completion {
self?.error = error.localizedDescription
}
} receiveValue: { [weak self] user in
self?.createRecord(for: user)
}
.store(in: &subscriptions)
}
func createRecord(for user: User) {
DatabaseManager.shared.collectionUsers(add: user)
.sink { [weak self] completion in
if case .failure(let error) = completion{
self?.error = error.localizedDescription
}
} receiveValue: { state in
print("Adding user record to database: \(state)")
}
.store(in: &subscriptions)
}
...
}
⭐️ handleEvents?
- 게시자 (publisher)의 이벤트가 발생할 떄 특정 클로저를 실행하는데 사용된다.
- 여기서는 user 정보에 대한 변동사항? 이 있을 떄를 이를 통해 계정 정보를 저장하기 위함 (createRecord 사용)이다.

4️⃣ ViewModels 폴더 내에 HomeViewViewModel 파일 생성
- TwitterUser 구조체 타입의 user의 정보를 관리하기 위함
import Foundation
import Combine
import FirebaseAuth
final class HomeViewViewModel: ObservableObject {
@Published var user: TwitterUser?
@Published var error: String?
private var subscriptions: Set<AnyCancellable> = []
func retreiveUser() {
guard let id = Auth.auth().currentUser?.uid else { return }
DatabaseManager.shared.collectionUsers(retreive: id)
.handleEvents(receiveOutput: { [weak self] user in
self?.user = user
})
.sink { [weak self] completion in
if case .failure(let error) = completion {
self?.error = error.localizedDescription
}
} receiveValue: { [weak self] user in
self?.user = user
}
.store(in: &subscriptions)
}
}
5️⃣ Networking 폴더 내에 DatabaseManager 파일에 collectionsUsers(retreive ~) 메서드 추가
class DatabaseManager {
static let shared = DatabaseManager()
let db = Firestore.firestore()
let usersPath: String = "users"
let tweetsPath: String = "tweets"
...
func collectionUsers(retreive id: String) -> AnyPublisher<TwitterUser, Error> {
db.collection(usersPath).document(id).getDocument()
.tryMap { try $0.data(as: TwitterUser.self) }
.eraseToAnyPublisher()
}
6️⃣ HomeViewController 파일 내 사용자 반환 메서드 구현
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.navigationBar.isHidden = false
// 로그인 여부 확인
handleAuthentication()
// 뷰가 새로 열릴 때마다 사용자에 대한 정보 확인
viewModel.retreiveUser()
}
- 사용자의 정보 유무에 따른 Profile뷰 열기
func completeUserOnboarding() {
let profileDataFormVC = ProfileDataFormViewController()
present(profileDataFormVC, animated: true)
}
func bindViews() {
viewModel.$user.sink { [weak self] user in
guard let user = user else { return }
if !user.isUserOnboarded {
self?.completeUserOnboarding()
}
}
.store(in: &subscriptions)
}
'Clone App > Twitter' 카테고리의 다른 글
[Twitter Clone] Connect to Firebase Storage (0) | 2024.06.12 |
---|---|
[Twitter Clone] Add ProfileDataFormView (0) | 2024.06.11 |
[Twitter Clone] Add signOut, Login View, Error View (0) | 2024.06.06 |
[Twitter Clone] Add ViewModel and bind view (0) | 2024.06.05 |
[Twitter Clone] Add Firebase to App (setup onboarding view controllers) (0) | 2024.06.04 |