đ´ Let's Build Twitter with SwiftUI (iOS 15, Xcode 13, Firebase, SwiftUI 3.0)
ObservableObject
ëĄ ě ě¸ë 롰 모ë¸ě í경ëłě ę´ëŚŹfunc login(email: String, password: String) {
Auth.auth().signIn(withEmail: email, password: password) { [weak self] userResult, error in
guard
let userResult = userResult,
error == nil else { return }
self?.userSession = userResult.user
print("Firebase Login Did Succeed")
}
}
ObservableObject
í´ëě¤@Published
íě
ě ě¤ë¸ě í¸ ę° ëłę˛˝func register(email: String, password: String, userName: String, fullName: String) {
Auth.auth().createUser(withEmail: email, password: password) { [weak self] userResult, error in
guard
let userResult = userResult,
error == nil else { return }
print("Firebase Register Did Succeed")
let data = ["email": email, "userName": userName.lowercased(), "fullName": fullName, "uid": userResult.user.uid]
Firestore.firestore().collection("users")
.document(userResult.user.uid)
.setData(data) { [weak self] error in
if let error = error {
print(error.localizedDescription)
} else {
self?.didAuthenticateUser = true
print("Firestore Register Did Succeed")
}
}
}
}
didAuthenticateUser
ëĄ ě´ëNavigationLink(destination: ProfilePhotoSelectorView(), isActive: $viewModel.didAuthenticateUser) {
EmptyView()
}
@Published
ëłěě¸ didAuthenticatieUser
뼟 ę´ě°°í ë¤ isActive
뼟 íľí´ í¸ěŹěí¤ë ë¤ëšę˛ě´ě
ë§íŹimport SwiftUI
import Firebase
@main
struct TwitterCloneApp: App {
@StateObject private var viewModel = AuthViewModel()
init() {
FirebaseApp.configure()
}
var body: some Scene {
WindowGroup {
NavigationView {
ContentView()
}
.navigationViewStyle(.stack)
.environmentObject(viewModel)
}
}
}
@StateObject
ëĄ í´ëš ObservableObject
ě ě¸environmentObject
뼟 íľí´ í´ëš í´ëě¤ëĽź íëźëŻ¸í°ëĄ ë겨죟기import SwiftUI
struct ContentView: View {
@EnvironmentObject var viewModel: AuthViewModel
@State private var showMenu: Bool = false
var body: some View {
Group {
// if no user logged in
if viewModel.userSession == nil {
LoginView()
} else {
// if user logged in
mainInterfaceView
}
}
}
}
userSession
ę°ě ëĄęˇ¸ě¸ ëą íě´ě´ë˛ ě´ě¤ í¨ě ěŹěŠ ë¤ ę° ëłí뼟 ę°ě§ ę°ëĽimport SwiftUI
struct RegistrationView: View {
@EnvironmentObject var viewModel: AuthViewModel
@State private var email: String = ""
@State private var userName: String = ""
@State private var fullName: String = ""
@State private var password: String = ""
@Environment(\.presentationMode) var mode
var body: some View {
ZStack {
VStack {
AuthenticationHeaderView(title: "Get Started.\nCreate your account")
VStack(spacing: 40) {
CustomInputField(imageName: "envelope", placeholderText: "Email", isSecureField: false, text: $email)
CustomInputField(imageName: "person", placeholderText: "UserName", isSecureField: false,text: $userName)
CustomInputField(imageName: "person", placeholderText: "Full Name", isSecureField: false,text: $fullName)
CustomInputField(imageName: "lock", placeholderText: "Password", isSecureField: true, text: $password)
}
.padding(32)
Button {
viewModel.register(email: email, password: password, userName: userName, fullName: fullName)
print("Button clicked from register view")
} label: {
Text("Sign Up")
.font(.headline)
.foregroundColor(.white)
.frame(width: 340, height: 50)
.background(Color(.systemBlue))
.clipShape(Capsule())
.padding()
}
.shadow(color: .gray.opacity(0.5), radius: 10, x: 0, y: 0)
Spacer()
Button {
mode.wrappedValue.dismiss()
} label: {
HStack {
Text("Already have an account?")
.font(.footnote)
Text("Sign In")
.font(.footnote)
.fontWeight(.semibold)
}
}
.padding(.bottom, 32)
}
.ignoresSafeArea()
NavigationLink(destination: ProfilePhotoSelectorView(), isActive: $viewModel.didAuthenticateUser) {
EmptyView()
}
}
}
}
import SwiftUI
struct ProfilePhotoSelectorView: View {
var body: some View {
VStack {
AuthenticationHeaderView(title: "Create your account\nAdd a profile photo")
Button {
print("Pick Image here...")
} label: {
Image("tweet_plus")
.resizable()
.scaledToFit()
.frame(width: 180, height: 180)
.padding(.top, 44)
}
Spacer()
}
.ignoresSafeArea()
}
}
import SwiftUI
import FirebaseAuth
import FirebaseFirestore
class AuthViewModel: ObservableObject {
@Published var userSession: FirebaseAuth.User?
@Published var didAuthenticateUser = false
init() {
self.userSession = Auth.auth().currentUser
}
func login(email: String, password: String) {
Auth.auth().signIn(withEmail: email, password: password) { [weak self] userResult, error in
guard
let userResult = userResult,
error == nil else { return }
self?.userSession = userResult.user
print("Firebase Login Did Succeed")
}
}
func register(email: String, password: String, userName: String, fullName: String) {
Auth.auth().createUser(withEmail: email, password: password) { [weak self] userResult, error in
guard
let userResult = userResult,
error == nil else { return }
print("Firebase Register Did Succeed")
let data = ["email": email, "userName": userName.lowercased(), "fullName": fullName, "uid": userResult.user.uid]
Firestore.firestore().collection("users")
.document(userResult.user.uid)
.setData(data) { [weak self] error in
if let error = error {
print(error.localizedDescription)
} else {
self?.didAuthenticateUser = true
print("Firestore Register Did Succeed")
}
}
}
}
func signOut() {
do {
try Auth.auth().signOut()
userSession = nil
didAuthenticateUser = false
print("Firebase SignOut Did Succeed")
} catch {
print(error.localizedDescription)
}
}
}
ObservableObject
íëĄí ě˝ě ě¤ěíë í´ëě¤ëĄ @Pbulished
ëĄ ë ę°ě ëłí뼟 ę°ě§í´ěź í ë íźë¸ëŚŹě
ëĄ ěŁźę¸°