Swift 4 Firebase display group of users on TableView - swift

How i can display users with unique role on TableView. For example i want to display users only with role "user", or only with role "guest".
my User model:
import Foundation
import Firebase
class User: NSObject {
var id: String?
var name: String?
var login: String?
var email: String?
var profileImageUrl: String?
var role: String?
var isOnline: String?
init(dictionary: [String: AnyObject]) {
self.isOnline = dictionary["isOnline"] as? String
self.id = dictionary["userID"] as? String
self.name = dictionary["name"] as? String
self.login = dictionary["username"] as? String
self.email = dictionary["email"] as? String
self.profileImageUrl = dictionary["profileImageUrl"] as? String
self.role = dictionary["role"] as? String
}
}
My Firebase user model:

You could simple filter the array of users by the role.
self.guests = self.users.filter({$0.role == "guest"})
Then display the list of guests just like any other UITableView.

Related

Unpacking Firestore array with objects to a model in swift

I have a project in swift with Firestore for the database. My firestore dataset of a user looks like this. User details with an array that contains objects.
I have a function that gets the specifick user with all firestore data:
func fetchUser(){
db.collection("users").document(currentUser!.uid)
.getDocument { (snapshot, error ) in
do {
if let document = snapshot {
let id = document.documentID
let firstName = document.get("firstName") as? String ?? ""
let secondName = document.get("secondName") as? String ?? ""
let imageUrl = document.get("imageUrl") as? String ?? ""
let joinedDate = document.get("joinedDate") as? String ?? ""
let coins = document.get("coins") as? Int ?? 0
let challenges = document.get("activeChallenges") as? [Challenge] ?? []
let imageLink = URL(string: imageUrl)
let imageData = try? Data(contentsOf: imageLink!)
let image = UIImage(data: imageData!) as UIImage?
let arrayWithNoOptionals = document.get("activeChallenges").flatMap { $0 }
print("array without opt", arrayWithNoOptionals)
self.user = Account(id: id, firstName: firstName, secondName: secondName, email: "", password: "", profileImage: image ?? UIImage(), joinedDate: joinedDate, coins: coins, activeChallenges: challenges)
}
else {
print("Document does not exist")
}
}
catch {
fatalError()
}
}
}
This is what the user model looks like:
class Account {
var id: String?
var firstName: String?
var secondName: String?
var email: String?
var password: String?
var profileImage: UIImage?
var coins: Int?
var joinedDate: String?
var activeChallenges: [Challenge]?
init(id: String, firstName: String,secondName: String, email: String, password: String, profileImage: UIImage, joinedDate: String, coins: Int, activeChallenges: [Challenge]) {
self.id = id
self.firstName = firstName
self.secondName = secondName
self.email = email
self.password = password
self.profileImage = profileImage
self.joinedDate = joinedDate
self.coins = coins
self.activeChallenges = activeChallenges
}
init() {
}
}
The problem is I don't understand how to map the activeChallenges from firestore to the array of the model. When I try : let challenges = document.get("activeChallenges") as? [Challenge] ?? []
The print contains an empty array, but when i do: let arrayWithNoOptionals = document.get("activeChallenges").flatMap { $0 } print("array without opt", arrayWithNoOptionals)
This is the output of the flatmap:
it returns an optional array
System can not know that activeChallenges is array of Challenge object. So, you need to cast it to key-value type (Dictionary) first, then map it to Challenge object
let challengesDict = document.get("activeChallenges") as? [Dictionary<String: Any>] ?? [[:]]
let challenges = challengesDict.map { challengeDict in
let challenge = Challenge()
challenge.challengeId = challengeDict["challengeId"] as? String
...
return challenge
}
This is the same way that you cast snapshot(document) to Account object

Sort a custom dictionary by commentDate

This is my data in Firestore:
My comment model:
class CommentModel {
var commentText: String?
var commentDate: NSObject?
var uid: String?
var username : String?
var profileImageUrl: String?
init(dictionary: [String: Any]) {
commentText = dictionary["commentText"] as? String
commentDate = dictionary["commentDate"] as? NSObject
uid = dictionary["uid"] as? String
username = dictionary["username"] as? String
profileImageUrl = dictionary["profileImageUrl"] as? String
}
}
My comments dictionary contains all documents of "comments".
XCode gives me the following suggestion, but I am unsure how to use it.
self.comments.sorted { (CommentModel, CommentModel) -> Bool in
}
How can I sort my dictionary by the commentDate?
You need
self.comments.sort { $0.commentDate < $1.commentDate }
make sure comments is declared as var , also cast it as a Date or String
commentDate = dictionary["commentDate"] as? Date
OR
commentDate = dictionary["commentDate"] as? String

how map data from Firestore with nested struct in database with swift

Just how to read data from Firestore with nested struct in DB
with no nested struct it's ok.
struct Info {
let placeOfBirth: String
let year: String
}
struct User {
var userName: String
var email: String?
var info: Info
init?(data: [String: Any]) {
guard let userName = data["userName"] as? String,
let info = //???? I don't know how coding
else {return nil}
self.userName = userName
self.email = data["email"] as? String
self.info = ?????
}
}
// here I'd like to retrieve user.info...
How should be the code in swift to retrieve info.placeOfBirdh or info.year?
ty

Swift Firebase chat room

I have chat app with possibility send messages one to one (fromId/toId). I want to upgrade it with chat rooms. How i can do that? What DB structure do i need for ChatingRoom? What else i need to do that?
My User.swift model:
import Foundation
import Firebase
class User: NSObject {
var id: String?
var name: String?
var login: String?
var email: String?
var profileImageUrl: String?
var role: String?
var isOnline: String?
init(dictionary: [String: AnyObject]) {
self.isOnline = dictionary["isOnline"] as? String
self.id = dictionary["userID"] as? String
self.name = dictionary["name"] as? String
self.login = dictionary["username"] as? String
self.email = dictionary["email"] as? String
self.profileImageUrl = dictionary["profileImageUrl"] as? String
self.role = dictionary["role"] as? String
}
}
Message.swift model:
import UIKit
import Firebase
class Message: NSObject {
var fromId: String?
var text: String?
var timestamp: NSNumber?
var toId: String?
var imageUrl: String?
var videoUrl: String?
var imageWidth: NSNumber?
var imageHeight: NSNumber?
init(dictionary: [String: Any]) {
self.fromId = dictionary["fromId"] as? String
self.text = dictionary["text"] as? String
self.toId = dictionary["toId"] as? String
self.timestamp = dictionary["timestamp"] as? NSNumber
self.imageUrl = dictionary["imageUrl"] as? String
self.videoUrl = dictionary["videoUrl"] as? String
self.imageWidth = dictionary["imageWidth"] as? NSNumber
self.imageHeight = dictionary["imageHeight"] as? NSNumber
}
func chatPartnerId() -> String? {
return fromId == Auth.auth().currentUser?.uid ? toId : fromId
}
}
Well currently you have From / To.
So To is going to be a room rather than a person.
Users will need to be able to join a room (or rooms) in order to see the messages that are sent to that room.
So your need a Rooms node.
If you have a messages node then you can just sort by To (room) instead of To (user) to get all the messages sent in that chat room. From will always be the User that wrote the message

want to fetch userdata from firebase into a dictionary

I hope you could help me:
I try to fetch userdata from a firebase database into a user class and call "setValuesForKeys". I do understand that my class properties have to be exactly the same as in the firebase dictionary, but I've got the error "this class is not key value coding-compliant for the key city."
func fetchUsers(){
Database.database().reference().child("users").observe(.childAdded, with: { (snapshot) in
if let usersDictionary = snapshot.value as? [String: String] {
let users = Userdata()
users.setValuesForKeys(usersDictionary)
}
}, withCancel: nil)
}
And my user class is
class Userdata: NSObject {
var email: String?
var password: String?
var firstname: String?
var lastname: String?
var street: String?
var streetno: String?
var zipcode: String?
var city: String?
var phone: String? }
The snapshot from firebase looks like
Snap (ndLBXXX75Oe9Y1PXrqfISL8A4v82) {
city = Washington;
email = "1#a.com";
firstname = Andre;
lastname = Doe;
password = xxxxxx;
phone = "";
street = "Mainstreet";
streetno = 1;
zipcode = 11111;
}
And the dictionary from the database looks like
["city": Washington, "firstname": Andre, "lastname": Doe, "email": 1#a.com, "password": xxxxxx, "streetno": 1, "phone": , "street": Mainstreet, "zipcode": 11111]
I have a solution so far by using:
users.city = dictionary["city"]
My question / problem: I do want to understand the problem behind the error message "this class is not key value coding-compliant for the key city." because the key at the class and in the firebase snapshot looks like the same.
Working solution: I had to extend my user class. Now, the whole user class looks like:
Here is the code :
import Foundation
class UserData: NSObject {
var id: String?
var email: String?
var password: String?
var salutation: String?
var degree: String?
var firstname: String?
var lastname: String?
var street: String?
var streetno: String?
var zipcode: String?
var city: String?
var phone: String?
var profileImage: String?
init(dictionary: [String: Any]) {
self.city = dictionary["city"] as? String
self.id = dictionary["id"] as? String
self.email = dictionary["email"] as? String
self.salutation = dictionary["salutation"] as? String
self.degree = dictionary["degree"] as? String
self.firstname = dictionary["firstname"] as? String
self.lastname = dictionary["lastname"] as? String
self.password = dictionary["password"] as? String
self.phone = dictionary["phone"] as? String
self.street = dictionary["street"] as? String
self.streetno = dictionary["streetno"] as? String
self.zipcode = dictionary["zipcode"] as? String
self.profileImage = dictionary["profileImage"] as? String
}
}