메서드 구현
import Foundation
import FirebaseFirestore
import FirebaseFirestoreSwift
class MessagesManager: ObservableObject {
@Published private(set) var messages: [Message] = []
let db = Firestore.firestore()
init() {
getMessages()
}
func getMessages() {
db.collection("messages").addSnapshotListener { querySnapshot, error in
guard let documents = querySnapshot?.documents else {
print("Error fetching documents: \(String(describing: error))")
return
}
self.messages = documents.compactMap { document -> Message? in
do {
return try document.data(as: Message.self)
} catch {
print("Error decoding document into Message: \(error)")
return nil
}
}
self.messages.sort { $0.timestamp < $1.timestamp }
}
}
func sendMessage(text: String) {
do {
let newMessage = Message(id: "\(UUID())", text: text, received: false, timestamp: Date())
try db.collection("messages").document().setData(from: newMessage)
} catch {
print("Error adding message to Firestore: \(error)")
}
}
}
MessageManager에 새로운 메서드 sendMessage를 추가했다.
func sendMessage(text: String) {
do {
let newMessage = Message(id: "\(UUID())", text: text, received: false, timestamp: Date())
try db.collection("messages").document().setData(from: newMessage)
} catch {
print("Error adding message to Firestore: \(error)")
}
}
메서드는 getMessages 메서드와 반대로 Firebase에 데이터를 저장하는 역할을 한다.
TextField에서 입력된 내용을 파라미터로 받아 새로운 Message 객체를 생성하고, 이를 Firebase에 저장한다.
id를 생성할 때 사용한 UUID는 Swift에서 흔하게 사용하는 무작위 변수를 생성하는 메서드이다.
해당 메서드에 관한 내용은 위의 링크에서 확인할 수 있다.
메서드 호출하기
import SwiftUI
struct MessageField: View {
@EnvironmentObject var messagesManager: MessagesManager
@State private var message = ""
var body: some View {
HStack {
CustomTextField(placeholder: Text("Type your message."), text: $message)
Button{
messagesManager.sendMessage(text: message)
message = ""
} label: {
Image(systemName: "paperplane.fill")
.foregroundColor(.white)
.padding(10)
.background(Color("Yellow"))
.cornerRadius(50)
}
}
.padding(.horizontal)
.padding(.vertical, 10)
.background(Color("Gray"))
.cornerRadius(50)
.padding()
}
}
struct MessageField_Previews: PreviewProvider {
static var previews: some View {
MessageField()
.environmentObject(MessagesManager())
}
}
struct CustomTextField: View {
var placeholder: Text
@Binding var text: String
var editingChanged: (Bool) -> () = {_ in}
var commit: () -> () = {}
var body: some View {
ZStack(alignment: .leading) {
if text.isEmpty {
placeholder
.opacity((0.5))
}
TextField("", text: $text, onEditingChanged: editingChanged, onCommit: commit)
}
}
}
실제로 메서드를 호출하는 곳은 TextField의 Button이다.
따라서 해당 View에서 EnvironmentObject 변수로 MessageManager 형식의 인스턴스를 하나 생성한다.
EnvironmentObject를 추가했기 때문에 Preview에도 이를 적용해야 함을 잊지 말자.
Button{
messagesManager.sendMessage(text: message)
message = ""
} label: {
Image(systemName: "paperplane.fill")
.foregroundColor(.white)
.padding(10)
.background(Color("Yellow"))
.cornerRadius(50)
}
버튼은 이제 sendMessage 메서드를 호출하기만 하면 된다.
import SwiftUI
struct ContentView: View {
@StateObject var messagesManager = MessagesManager()
var body: some View {
VStack {
VStack {
TitleRow()
ScrollViewReader { proxy in
ScrollView {
ForEach(messagesManager.messages, id: \.id) { message in
MessageBubble(message: message)
}
}
.padding(.top, 10)
.background(.white)
.cornerRadius(30, corners: [.topLeft, .topRight])
.onChange(of: messagesManager.lastMessageId) { id in
withAnimation {
proxy.scrollTo(id, anchor: .bottom)
}
}
}
}
.background(Color("Yellow"))
MessageField()
.environmentObject(MessagesManager())
}
.onTapGesture {
hideKeyboard()
}
}
}
#if canImport(UIKit)
extension View {
func hideKeyboard() {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
}
#endif
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
MessageField에 생성된 MessagesManager 변수는 MessageField를 호출하는 ContentView에서 전달하게 된다.
11번 라인의 messageManager를 그대로 전달하면 된다.
전송한 메시지가 서버에 즉시 저장되는 걸 확인할 수 있다.
'프로젝트 > ChatApp ver.1 (w/Firebase)' 카테고리의 다른 글
05. 더 나아가기 (0) | 2022.10.15 |
---|---|
03. Firebase 초기화 및 Swift에서 사용하기 (0) | 2022.10.13 |
02. Firebase 연결하기 (0) | 2022.10.13 |
01. 인터페이스 디자인 (0) | 2022.10.11 |
00. 시작하며 (0) | 2022.10.11 |