🔴 Let's Build Twitter with SwiftUI (iOS 15, Xcode 13, Firebase, SwiftUI 3.0)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
if let profileImage = viewModel.profileImage {
Button {
withAnimation(.easeInOut) {
showMenu.toggle()
}
} label: {
Image(uiImage: profileImage)
.resizable()
.scaledToFill()
.frame(width: 32, height: 32)
.clipShape(Circle())
}
}
}
}
@Published var userSession: FirebaseAuth.User? {
didSet {
fetchUser()
}
}
didSet
에 위치func fetchUser() {
guard let uid = userSession?.uid else {
currentUser = nil
profileImage = nil
return
}
service.fetchUser(with: uid) { [weak self] result in
switch result {
case .failure(let error):
print(error.localizedDescription)
case .success(let user):
self?.currentUser = user
self?.downloadProfileImage(with: user.profileImageURL)
}
}
}
uid
를 다큐먼트 아이디로 사용, 유저 정보 데이터 패치struct UserService {
func fetchUser(with uid: String, completion: @escaping(Result<UserModel, Error>) -> Void) {
Firestore.firestore().collection("users")
.document(uid)
.getDocument { document, error in
guard
let document = document,
let user = try? document.data(as: UserModel.self) else {
if let error = error {
completion(.failure(error))
} else {
completion(.failure(URLError(.badURL)))
}
return
}
completion(.success(user))
}
}
}
private func downloadProfileImage(with urlString: String) {
guard let url = URL(string: urlString) else { return }
URLSession.shared.dataTask(with: url) { [weak self] data, response, error in
guard
let response = response as? HTTPURLResponse,
response.statusCode >= 200,
response.statusCode < 400,
error == nil,
let data = data,
let image = UIImage(data: data) else { return }
DispatchQueue.main.async { [weak self] in
self?.profileImage = image
}
}
.resume()
}
profileImage
에 해당 값을 넣어줌으로써 해당 값을 관찰 중인 실제 뷰에서 UI 인터렉션 가능if let profileImage = authViewModel.profileImage {
Image(uiImage: profileImage)
.resizable()
.scaledToFill()
.clipShape(Circle())
.frame(width: 48, height: 48)
}
유저 정보를 관리하는 뷰 모델을 환경 변수로 받고 있으니 매우 편리하게 사용하지만, 과연 메모리 누수 문제는 없을지 걱정이 된다. 물론 현재 환경에서는 모든 뷰에서 해당 유저 정보에 접근 가능해야 한다는 점에서 매우 효율적이지만, 어느 시점에서 적절하게 DI를 통해 의존성을 낮출 수 있을까?