Why I am not able to register user info to firebase in SwiftUI App? - swift

I have register screen and I am not able to register user info to firebase,
I put user info on simulator, but it just hold on on screen, and no any change on firebase, I guess maybe there is missed points on
CreateUser
function, any idea?
import SwiftUI
import Firebase
struct Register: View {
#State var name = ""
#State var about = ""
#Binding var show : Bool
var body: some View {
VStack(alignment: .center, spacing: 3){
TextField("Name",text:self.$name)
.padding()
TextField(" about", text: self.$about)
.padding()
if self.loading{
HStack{
Spacer()
Indicator()
Spacer()
}
}
else{
Button {
if self.name != "" && self.about != "" {
self.loading.toggle()
CreateUser(name: self.name, about: self.about) { (status) in
if status{
self.show.toggle()
}
}
}
else{
self.alert.toggle()
}
} label: {
Text("Next")
.padding()
}
}
}
user:
import Foundation
import Firebase
func CreateUser(name: String,about : String, completion : #escaping (Bool)-> Void){
let db = Firestore.firestore()
let storage = Storage.storage().reference()
let uid = Auth.auth().currentUser?.uid
db.collection("users").document(uid!).setData(["name":name,"about":about, "uid":uid!]) { (err) in
if err != nil{
print((err?.localizedDescription)!)
return
}
completion(true)
UserDefaults.standard.set(true, forKey: "status")
UserDefaults.standard.set(name, forKey: "UserName")
NotificationCenter.default.post(name: NSNotification.Name("statusChange"), object: nil)
}
}

Related

Why is it that every time I call fetchfollowingposts, the post user changes?

Any time the function "fetchfollowingposts" is called, the user's information in the feed cell changes. I've saved the post to firebase with the user's uid and i'm trying to fetch their profilephoto, fullname, etc. from the uid tied to the post. Any time I refresh the feedview, the user's information changes but the post itself never does (timestamp, post caption, post image, likes).
Since I don't fully understand the problem, I wasn't sure what files are needed so just let me know if i missed one. Thank you in advance for any help!
FeedCellView
import SwiftUI
import Kingfisher
struct FeedCell: View {
#ObservedObject var viewModel: FeedCellViewModel
#State private var isShowingBottomSheet = false
var didLike: Bool { return viewModel.post.didLike ?? false }
#Environment(\.presentationMode) var mode
init(viewModel: FeedCellViewModel) {
self.viewModel = viewModel
}
var body: some View {
VStack (alignment: .leading, spacing: 16) {
NavigationLink {
if let user = viewModel.post.user {
LazyView(ProfileView(user: user))
}
} label: {
HStack (alignment: .top) {
KFImage(URL(string: viewModel.post.user?.profileImageUrl ?? "https://firebasestorage.googleapis.com/v0/b/pageturner-951b4.appspot.com/o/profile_image%2FNoProfilePhoto.png?alt=media&token=1055648d-4d6e-4d51-b003-948a47b6bb76"))
.resizable()
.scaledToFill()
.frame(width: 48, height: 48)
.cornerRadius(10)
VStack (alignment: .leading, spacing: 4) {
Text(viewModel.post.user?.fullname ?? "")
.font(.system(size: 16))
.foregroundColor(Color(.label))
Text(viewModel.timestampString)
.font(.system(size: 14))
.foregroundColor(.gray)
}
Spacer()
if viewModel.post.isCurrentUser {
Button {
isShowingBottomSheet.toggle()
} label: {
Image(systemName: "ellipsis")
}.foregroundColor(Color(.gray))
.confirmationDialog("What do you want to do?",
isPresented: $isShowingBottomSheet) {
Button("Delete post", role: .destructive) {
viewModel.deletePost()
}
} message: {
Text("You cannot undo this action")
}
}
}
}
Text(viewModel.post.caption)
.font(.system(size: 16))
if let image = viewModel.post.imageUrl {
KFImage(URL(string: image))
.resizable()
.scaledToFill()
.frame(maxHeight: 250)
.cornerRadius(10)
}
HStack {
HStack (spacing: 24) {
Button {
didLike ? viewModel.unlike() : viewModel.like()
} label: {
Image(didLike ? "heart.fill" : "heart")
.renderingMode(.template)
.resizable()
.foregroundColor(didLike ? Color.accentColor : .black)
.frame(width: 24, height: 24)
Text("\(viewModel.post.likes)")
}
NavigationLink {
CommentView(post: viewModel.post)
} label: {
Image("comment")
.renderingMode(.template)
.resizable()
.frame(width: 24, height: 24)
Text("\(viewModel.post.stats?.CommentCount ?? 0)")
}
}
Spacer()
}
.foregroundColor(Color(.label))
}
}
}
FeedService
import SwiftUI
import FirebaseCore
import FirebaseAuth
import FirebaseFirestore
import FirebaseFirestoreSwift
struct FeedService {
func uploadPost(caption: String, image: UIImage?, completion: #escaping(Bool) -> Void) {
guard let uid = Auth.auth().currentUser?.uid else { return }
ImageUploader.uploadImage(image: image, type: .post) { imageUrl in
let data = ["uid": uid,
"caption": caption,
"likes": 0,
"imageUrl": imageUrl,
"timestamp": Timestamp(date: Date())] as [String: Any]
COLLECTION_POSTS.document()
.setData(data) { error in
if let error = error {
print("DEBUG: Failed to upload post with error: \(error.localizedDescription)")
completion(false)
return
}
}
completion(true)
}
}
func fetchFollowingPosts(forUid uid: String, completion: #escaping([Post]) -> Void) {
var posts = [Post]()
COLLECTION_FOLLOWING.document(uid).collection("user-following")
.getDocuments { snapshot, _ in
guard let documents = snapshot?.documents else { return }
documents.forEach { doc in
let userId = doc.documentID
COLLECTION_POSTS.whereField("uid", isEqualTo: userId)
.getDocuments { snapshot, _ in
guard let documents = snapshot?.documents else { return }
let post = documents.compactMap({ try? $0.data(as: Post.self) })
posts.append(contentsOf: post)
completion(posts.sorted(by: { $0.timestamp.dateValue() > $1.timestamp.dateValue()
}))
}
}
}
}
func uploadStory(caption: String?, image: UIImage, rating: Int?, completion: #escaping(Bool) -> Void) {
guard let uid = Auth.auth().currentUser?.uid else { return }
ImageUploader.uploadImage(image: image, type: .story) { imageUrl in
let data = ["uid": uid,
"caption": caption ?? "",
"imageUrl": imageUrl,
"rating": rating ?? "",
"isSeen": false,
"timestamp": Timestamp(date: Date())] as [String: Any]
COLLECTION_STORIES.document()
.setData(data) { error in
if let error = error {
print("DEBUG: Failed to upload story with error: \(error.localizedDescription)")
completion(false)
return
}
}
completion(true)
}
}
func fetchFollowingStories(forUid uid: String, completion: #escaping([Story]) -> Void) {
var stories = [Story]()
COLLECTION_FOLLOWING.document(uid).collection("user-following")
.getDocuments { snapshot, _ in
guard let documents = snapshot?.documents else { return }
documents.forEach { doc in
let userId = doc.documentID
COLLECTION_STORIES.whereField("uid", isEqualTo: userId)
.getDocuments { snapshot, _ in
guard let documents = snapshot?.documents else { return }
let story = documents.compactMap({ try? $0.data(as: Story.self) })
stories.append(contentsOf: story)
completion(stories.sorted(by: { $0.timestamp.dateValue() > $1.timestamp.dateValue()
}))
}
}
}
}
}
FeedViewModel
import SwiftUI
class FeedViewModel: ObservableObject {
#Published var followingPosts = [Post]()
#Published var followingStories = [Story]()
let service = FeedService()
let userService = UserService()
init() {
fetchFollowingPosts()
fetchFollowingStories()
}
func fetchFollowingPosts() {
guard let userid = AuthViewModel.shared.userSession?.uid else { return }
service.fetchFollowingPosts(forUid: userid) { posts in
self.followingPosts = posts
for i in 0 ..< posts.count {
let uid = posts[i].uid
self.userService.fetchUser(withUid: uid) { user in
self.followingPosts[i].user = user
}
}
}
}
func fetchFollowingStories() {
guard let userid = AuthViewModel.shared.userSession?.uid else { return }
service.fetchFollowingStories(forUid: userid) { stories in
self.followingStories = stories
for i in 0 ..< stories.count {
let uid = stories[i].uid
self.userService.fetchUser(withUid: uid) { user in
self.followingStories[i].user = user
}
}
}
}
}

List not re-loading from firestore in base view on dismiss of .sheet in SwiftUI

I have another question.
I have a demo app where I add a ToDo in a Firestore database. From the base View I open a .sheet with a TextEditor where I enter data and save it into Firestore database. But on dismiss the List of ToDos in the base View is gone and is not refreshed until I go to another tab in the app and return back.
I have a ViewModel where I use a Firebase snapshot listener.
Code of the base View:
import Firebase
import Foundation
import SwiftUI
import FirebaseStorage
struct HomeMenuView: View {
#ObservedObject var toDosViewModel = ToDosViewModel()
#Binding var showAddToDoView: Bool
#State private var showModifyToDoView = false
#State private var note = ""
#State private var selectedToDoId = ""
func removeRow(at offset:IndexSet) {
for index in offset {
toDosViewModel.deleteNote(noteToDelete: toDosViewModel.todos[index].id!)
}
}
var body: some View {
ZStack{
VStack (alignment: .center){
List() {
ForEach(toDosViewModel.todos) { todo in
VStack(alignment: .leading, spacing: 10) {
Text(todo.notes)
.font(.subheadline)
.foregroundColor(Color.tabBarColor)
.lineLimit(2)
.onTapGesture {
showAddToDoView = true
selectedToDoId = todo.id!
note = todo.notes
}
}
.listRowSeparatorTint(Color.tabBarColor)
}
.onDelete(perform: removeRow)
}
.listStyle(InsetGroupedListStyle())
.onAppear() {
toDosViewModel.subscribe()
}
}
}
.sheet(isPresented: $showAddToDoView) {
VStack() {
HStack () {
Button("Save") {
guard !note.isEmpty else
{ showAddToDoView = false; return }
toDosViewModel.addNote(notes: note)
note = ""
showAddToDoView = false
}
.offset(x: 20)
Spacer()
Button("Back") {
note = ""
showAddToDoView = false
}
.offset(x: -20)
}
.frame(height: 50, alignment: .center)
TextEditor(
text: $note
)
}
}
}
}
The ViewModel:
import Foundation
import FirebaseFirestore
import FirebaseFirestoreSwift
import UIKit
class ToDosViewModel: ObservableObject {
#Published var todos = [ToDo]()
#Published var errorMessage: String?
private var db = Firestore.firestore()
private var listenerRegistration: ListenerRegistration?
func subscribe() {
if listenerRegistration == nil {
listenerRegistration = db.collection("todos")
.order(by: "timestamp", descending: true)
.addSnapshotListener { [weak self] (querySnapshot, error) in
guard let documents = querySnapshot?.documents else {
print("No documents")
return
}
self?.todos = documents.compactMap { queryDocumentSnapshot in
let result = Result { try queryDocumentSnapshot.data(as: ToDo.self) }
switch result {
case .success(let todo):
if let todo = todo {
self?.errorMessage = nil
return todo
}
else {
self?.errorMessage = "Document doesn't exist."
return nil
}
case .failure(let error):
switch error {
case DecodingError.typeMismatch(_, let context):
self?.errorMessage = "\(error.localizedDescription): \(context.debugDescription)"
case DecodingError.valueNotFound(_, let context):
self?.errorMessage = "\(error.localizedDescription): \(context.debugDescription)"
case DecodingError.keyNotFound(_, let context):
self?.errorMessage = "\(error.localizedDescription): \(context.debugDescription)"
case DecodingError.dataCorrupted(let key):
self?.errorMessage = "\(error.localizedDescription): \(key)"
default:
self?.errorMessage = "Error decoding document: \(error.localizedDescription)"
}
return nil
}
}
}
}
}
func addNote(notes: String) {
db.collection("todos").document().setData(["notes" : notes, "timestamp" : FieldValue.serverTimestamp()])
}
func modifyNote(noteToModify: String, notes: String) {
db.collection("todos").document(noteToModify).setData(["notes" : notes, "timestamp" : FieldValue.serverTimestamp()])
}
func deleteNote(noteToDelete: String) {
db.collection("todos").document(noteToDelete).delete()
}
}
Any idea what the issue could be?
Thanks a lot for your support.
Change
#ObservedObject var toDosViewModel = ToDosViewModel()
To
#StateObject var toDosViewModel = ToDosViewModel()

SwiftUI: View does not update after image changed asynchronous

As mentioned in the headline, I try to load images to a custom object
I’ve got the custom object “User” that contains the property “imageLink” that stores the location within the Firebase Storage.
First I load the users frome the Firestore db and then I try to load the images for these users asynchronous from the Firebase Storage and show them on the View. As long as the image has not been loaded, a placeholder shall be shown.
I tried several implementations and I always can see in the debugger that I am able to download the images (I saw the actual image and I saw the size of some 100kb), but the loaded images don’t show on the view, I still see the placeholder, it seems that the view does not update after they loaded completely.
From my perspective, the most promising solution was:
FirebaseImage
import Combine
import FirebaseStorage
import UIKit
let placeholder = UIImage(systemName: "person")!
struct FirebaseImage : View {
init(id: String) {
self.imageLoader = Loader(id)
}
#ObservedObject private var imageLoader : Loader
var image: UIImage? {
imageLoader.data.flatMap(UIImage.init)
}
var body: some View {
Image(uiImage: image ?? placeholder)
}
}
Loader
import SwiftUI
import Combine
import FirebaseStorage
final class Loader : ObservableObject {
let didChange = PassthroughSubject<Data?, Never>()
var data: Data? = nil {
didSet { didChange.send(data) }
}
init(_ id: String){
// the path to the image
let url = "profilepics/\(id)"
print("load image with id: \(id)")
let storage = Storage.storage()
let ref = storage.reference().child(url)
ref.getData(maxSize: 1 * 1024 * 1024) { data, error in
if let error = error {
print("\(error)")
}
DispatchQueue.main.async {
self.data = data
}
}
}
}
User
import Foundation
import Firebase
import CoreLocation
import SwiftUI
struct User: Codable, Identifiable, Hashable {
var id: String?
var name: String
var imageLink: String
var imagedata: Data = .init(count: 0)
init(name: String, imageLink: String, lang: Double) {
self.id = id
self.name = name
self.imageLink = imageLink
}
init?(document: QueryDocumentSnapshot) {
let data = document.data()
guard let name = data["name"] as? String else {
return nil
}
guard let imageLink = data["imageLink"] as? String else {
return nil
}
id = document.documentID
self.name = name
self.imageLink = imageLink
}
}
extension User {
var image: Image {
Image(uiImage: UIImage())
}
}
extension User: DatabaseRepresentation {
var representation: [String : Any] {
var rep = ["name": name, "imageLink": imageLink] as [String : Any]
if let id = id {
rep["id"] = id
}
return rep
}
}
extension User: Comparable {
static func == (lhs: User, rhs: User) -> Bool {
return lhs.id == rhs.id
}
static func < (lhs: User, rhs: User) -> Bool {
return lhs.name < rhs.name
}
}
UserViewModel
import Foundation
import FirebaseFirestore
import Firebase
class UsersViewModel: ObservableObject {
let db = Firestore.firestore()
let storage = Storage.storage()
#Published var users = [User]()
#Published var showNewUserName: Bool = UserDefaults.standard.bool(forKey: "showNewUserName"){
didSet {
UserDefaults.standard.set(self.showNewUserName, forKey: "showNewUserName")
NotificationCenter.default.post(name: NSNotification.Name("showNewUserNameChange"), object: nil)
}
}
#Published var showLogin: Bool = UserDefaults.standard.bool(forKey: "showLogin"){
didSet {
UserDefaults.standard.set(self.showLogin, forKey: "showLogin")
NotificationCenter.default.post(name: NSNotification.Name("showLoginChange"), object: nil)
}
}
#Published var isLoggedIn: Bool = UserDefaults.standard.bool(forKey: "isLoggedIn"){
didSet {
UserDefaults.standard.set(self.isLoggedIn, forKey: "isLoggedIn")
NotificationCenter.default.post(name: NSNotification.Name("isLoggedInChange"), object: nil)
}
}
func addNewUserFromData(_ name: String, _ imageLing: String, _ id: String) {
do {
let uid = Auth.auth().currentUser?.uid
let newUser = User(name: name, imageLink: imageLing, lang: 0, long: 0, id: uid)
try db.collection("users").document(newUser.id!).setData(newUser.representation) { _ in
self.showNewUserName = false
self.showLogin = false
self.isLoggedIn = true
}
} catch let error {
print("Error writing city to Firestore: \(error)")
}
}
func fetchData() {
db.collection("users").addSnapshotListener { (querySnapshot, error) in
guard let documents = querySnapshot?.documents else {
print("No documents")
return
}
self.users = documents.map { queryDocumentSnapshot -> User in
let data = queryDocumentSnapshot.data()
let id = data["id"] as? String ?? ""
let name = data["name"] as? String ?? ""
let imageLink = data["imageLink"] as? String ?? ""
let location = data["location"] as? GeoPoint
let lang = location?.latitude ?? 0
let long = location?.longitude ?? 0
Return User(name: name, imageLink: imageLink, lang: lang, long: long, id: id)
}
}
}
}
UsersCollectionView
import SwiftUI
struct UsersCollectionView: View {
#Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
#EnvironmentObject var usersViewModel: UsersViewModel
let itemWidth: CGFloat = (screenWidth-30)/4.2
let itemHeight: CGFloat = (screenWidth-30)/4.2
var fixedLayout: [GridItem] {
[
.init(.fixed((screenWidth-30)/4.2)),
.init(.fixed((screenWidth-30)/4.2)),
.init(.fixed((screenWidth-30)/4.2)),
.init(.fixed((screenWidth-30)/4.2))
]
}
func debugUserValues() {
for user in usersViewModel.users {
print("ID: \(user.id), Name: \(user.name), ImageLink: \(user.imageLink)")
}
}
var body: some View {
VStack() {
ScrollView(showsIndicators: false) {
LazyVGrid(columns: fixedLayout, spacing: 15) {
ForEach(usersViewModel.users, id: \.self) { user in
VStack() {
FirebaseImage(id: user.imageLink)
HStack(alignment: .center) {
Text(user.name)
.font(.system(size: 16))
.fontWeight(.bold)
.foregroundColor(Color.black)
.lineLimit(1)
}
}
}
}
.padding(.top, 20)
Rectangle()
.fill(Color .clear)
.frame(height: 100)
}
}
.navigationTitle("Find Others")
.navigationBarBackButtonHidden(true)
.navigationBarItems(leading:
Button(action: {
self.presentationMode.wrappedValue.dismiss()
}) {
HStack {
Image(systemName: "xmark")
.foregroundColor(.black)
.padding()
.offset(x: -15)
}
})
}
}
You're using an old syntax from BindableObject by using didChange -- that system changed before SwiftUI 1.0 was out of beta.
A much easier approach would be to use #Published, which your view will listen to automatically:
final class Loader : ObservableObject {
#Published var data : Data?
init(_ id: String){
// the path to the image
let url = "profilepics/\(id)"
print("load image with id: \(id)")
let storage = Storage.storage()
let ref = storage.reference().child(url)
ref.getData(maxSize: 1 * 1024 * 1024) { data, error in
if let error = error {
print("\(error)")
}
DispatchQueue.main.async {
self.data = data
}
}
}
}

ListView in child view is not refreshed correctly

There is a ListView. I make a transaction in Cloud Firestore by changing the field of an element when I click on it in the list. Data in the database changes as it should, but after this action all the elements in the list disappear (although there is .onAppear {fetchData}). An important point: this is a child view, there is no such problem in the parent view.
I also added a button at the bottom of the list to execute fetchData (), when I click on it, the data returns to the list
What could be the problem? Thanks
import SwiftUI
struct SecondView: View {
#ObservedObject var viewModel = BooksViewModel()
var body: some View {
VStack {
List(viewModel.books) { book in
VStack(alignment: .leading) {
Button("Update data"){
let updBook = book
self.viewModel.myTransaction(book: updBook)
}
Text(book.title)
.font(.headline)
Text(book.author)
.font(.subheadline)
Text("\(book.numberOfPages) pages")
.font(.subheadline)
}
}
.navigationBarTitle("Books")
.onAppear() {
self.viewModel.fetchData()
}
Button("update list"){
self.viewModel.fetchData()
}
}
}
}
ViewModel:
import Foundation
import FirebaseFirestore
import FirebaseFirestoreSwift
class BooksViewModel: ObservableObject {
#Published var books = [Book]()
private var db = Firestore.firestore()
func fetchData() {
db.collection("books").addSnapshotListener { (querySnapshot, error) in
guard let documents = querySnapshot?.documents else {
print("No documents")
return
}
self.books = documents.compactMap { queryDocumentSnapshot -> Book? in
return try? queryDocumentSnapshot.data(as: Book.self)
}
}
}
func deleteBook(book: Book){
if let bookID = book.id{
db.collection("books").document(bookID).delete()
}
}
func updateBook(book: Book) {
if let bookID = book.id{
do {
try db.collection("books").document(bookID).setData(from: book) }
catch {
print(error)
}
}
}
func addBook(book: Book) {
do {
let _ = try db.collection("books").addDocument(from: book)
}
catch {
print(error)
}
}
func myTransaction(book: Book){
let bookID = book.id
let targetReference = db.collection("books").document(bookID!)
db.runTransaction({ (transaction, errorPointer) -> Any? in
let targetDocument: DocumentSnapshot
do {
try targetDocument = transaction.getDocument(targetReference)
} catch let fetchError as NSError {
errorPointer?.pointee = fetchError
return nil
}
guard let oldValue = targetDocument.data()?["pages"] as? Int else {
let error = NSError(
domain: "AppErrorDomain",
code: -1,
userInfo: [
NSLocalizedDescriptionKey: "Unable to retrieve population from snapshot \(targetDocument)"
]
)
errorPointer?.pointee = error
return nil
}
// Note: this could be done without a transaction
// by updating the population using FieldValue.increment()
transaction.updateData(["pages": oldValue + 1], forDocument: targetReference)
return nil
}) { (object, error) in
if let error = error {
print("Transaction failed: \(error)")
} else {
print("Transaction successfully committed!")
}
}
}
}
Parent view:
import SwiftUI
struct ContentView: View {
#ObservedObject var viewModel = BooksViewModel()
var body: some View {
NavigationView {
VStack {
List(viewModel.books) { book in
VStack(alignment: .leading) {
Button("Update"){
let delBook = book
self.viewModel.myTransaction(book: delBook)
}
Text(book.title)
.font(.headline)
Text(book.author)
.font(.subheadline)
Text("\(book.numberOfPages) pages")
.font(.subheadline)
}
}
.navigationBarTitle("Books")
.onAppear() {
self.viewModel.fetchData()
}
NavigationLink(destination: SecondView()){
Text("Second View")
}
}
}
}
}
A possible solution might be that your Views and its ViewModels interfere with each other. It looks like you create two instances of the same BookViewModel:
struct ContentView: View {
#ObservedObject var viewModel = BooksViewModel()
struct SecondView: View {
#ObservedObject var viewModel = BooksViewModel()
Try creating one BooksViewModel and pass it between views (you can use an #EnvironmentObject).

Entries from text field are not adding into list

import SwiftUI
import Firebase
import FirebaseFirestore
struct ContentView: View {
var body: some View {
customView()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct customView : View{
#State var msg = ""
#ObservedObject var datas = observer()
var body : some View{
VStack{
List{
ForEach(datas.data){i in
Text(i.msg)
}
.onDelete { (index) in
let id = self.datas.data[index.first!].id
let db = Firestore.firestore().collection("msgs")
db.document(id).delete{(err) in
if err != nil{
print((err!.localizedDescription))
return
}
print("deleted Successfully !!!")
self.datas.data.remove(atOffsets: index)
}
}
}
HStack{
TextField("msg", text: $msg).textFieldStyle(RoundedBorderTextFieldStyle())
Button(action: {
print(self.msg)
self.addData(msg1: self.msg)
}) {
Text("Add")
}.padding()
}.padding()
}
}
func addData(msg1:String){ 'Here is the code for additon'
let db = Firestore.firestore()
let msg = db.collection("msgs").document()
msg.setData(["id":msg.documentID,"msg": msg1]) { (err) in
if err != nil{
print((err?.localizedDescription)!)
return
}
print("Success")
self.msg = ""
}
}
}
class observer : ObservableObject{
#Published var data = [datatype]()
init() {
let db = Firestore.firestore().collection("msg")
db.addSnapshotListener{(snap, err) in
if err != nil{
print((err?.localizedDescription)!)
return
}
for i in snap!.documentChanges{
if i.type == .added{
let msgData = datatype(id: i.document.documentID, msg: i.document.get("msg")
as! String)
self.data.append(msgData)
}
}
}
}
}
struct datatype : Identifiable {
var id : String
var msg : String
}
Here is the code for the CRUD(creation, reading, update, delete) using the firebase cloud service. When i enter the text in the text field and then hit button, it adds to firebase database, but doesn't shows up in the interface in the list of the app. Can anybody tell me where i am going wrong?
In this i am trying to add data to firebase, delete it ,read it and modify/update it. But the data entered doesn't shows up in interface.
Try to update data container explicitly on main thread, like below
if i.type == .added{
let msgData = datatype(id: i.document.documentID, msg: i.document.get("msg")
as! String)
DispatchQueue.main.async {
self.data.append(msgData)
}
}
as alternate try assignment instead of modification (however this should not be the case)
DispatchQueue.main.async {
self.data = self.data + [msgData]
}