Swift 4 Retrieving Data From Firebase Database - swift

func retPost2(){
runNBPOST()
////////////////////////////////////1
var pic = [String]()
var p = Post(userId: "", postId: "", postType: "", description: "", Region: "", City: "", District: "", Street: "", Area: 0, View: "", TotalPrice: 0, Pictures: pic, StreetWidth: 0, PropertyType: "")
////// for to retrive all post
print(retNBPOST())
runNBPOST()
let nbpost = retNBPOST()
for i in 1..<nbpost{
postiiD = "Post(\(i))"
self._REF_BASE.child("Post").child(postiiD).observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
let UserID2 = value?["UserID"] as? String ?? ""
p.userId = UserID2
})
self._REF_BASE.child("Post").child("\("Post(\(i))")/Adress").observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
let Region = value?["Region"] as? String ?? ""
p.Region = Region
let City = value?["City"] as? String ?? ""
p.City = City
print(p.City)
let District = value?["District"] as? String ?? ""
p.District = District
let Street = value?["Street"] as? String ?? ""
p.Street = Street
let AdditionalNumber = value?["AdditionalNumber"] as? String ?? ""
p.AdditionalNumber = AdditionalNumber
let PostalCode = value?["PostalCode"] as? String ?? ""
p.PostalCode = PostalCode
let BuldingNo = value?["BuldingNo"] as? String ?? ""
p.BuldingNo = BuldingNo
})
self._REF_BASE.child("Post").child("\(postiiD)/PostInfo").observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
let postType = value?["PostType"] as? String ?? ""
p.postType = postType
print(p.postType)
let DateOfpost = value?["DateOfpost"] as? String ?? ""
p.dateOfpost = DateOfpost
let EndDateOfPost = value?["EndDateOfPost"] as? String ?? ""
p.endDateOfPost = EndDateOfPost
let NbOfShare = value?["NbOfShare"] as? String ?? ""
p.nbOfShare = Int(NbOfShare)!
let NbOfViews = value?["NbOfViews"] as? String ?? ""
p.nbOfViews = Int(NbOfViews)!
let LastUpdate = value?["LastUpdate"] as? String ?? ""
p.lastUpdate = LastUpdate
let Description = value?["Description"] as? String ?? ""
p.description = Description
let Publisher = value?["Publisher"] as? String ?? ""
p.publisher = Publisher
let ContactTime = value?["ContactTime"] as? String ?? ""
p.contactTime = ContactTime
let Payment = value?["Payment"] as? String ?? ""
p.payment = Payment
let TotalPrice = value?["TotalPrice"] as? String ?? ""
p.TotalPrice = Double(TotalPrice)!
let NearBy = value?["NearBy"] as? String ?? ""
p.NearBy = NearBy
let StreetWidth = value?["StreetWidth"] as? String ?? ""
p.StreetWidth = Double(StreetWidth)!
// let Discount = value?["Discount"] as? String ?? ""
// p.Discount =
})
self._REF_BASE.child("Post").child("\(postiiD)/Property").observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
let Area = value?["Area"] as? String ?? ""
p.Area = Double(Area)!
print(p.Area)
let View = value?["View"] as? String ?? ""
p.View = View
let FamilyOrSingle = value?["FamilyOrSingle"] as? String ?? ""
p.FamilyOrSingle = FamilyOrSingle
let Level = value?["Level"] as? String ?? ""
p.Level = Int(Level)!
let HouseAge = value?["HouseAge"] as? String ?? ""
p.HouseAge = Int(HouseAge)!
let LandType = value?["LandType"] as? String ?? ""
p.LandType = LandType
let MeterPrice = value?["MeterPrice"] as? String ?? ""
p.MeterPrice = Double(MeterPrice)!
let NbRoom = value?["NbRoom"] as? String ?? ""
p.NbRoom = Int(NbRoom)!
let NbGuestroom = value?["NbGuestroom"] as? String ?? ""
p.NbGuestroom = Int(NbGuestroom)!
let NbBathroom = value?["NbBathroom"] as? String ?? ""
p.NbBathroom = Int(NbBathroom)!
let NbBedroom = value?["NbBedroom"] as? String ?? ""
p.NbBedroom = Int(NbBedroom)!
let NbLivingroom = value?["NbLivingroom"] as? String ?? ""
p.NbLivingroom = Int(NbLivingroom)!
let NbKitchen = value?["NbKitchen"] as? String ?? ""
p.NbKitchen = Int(NbKitchen)!
let PropertyType = value?["PropertyType"] as? String ?? ""
p.PropertyType = PropertyType
let NbApartment = value?["NbApartment"] as? String ?? ""
p.NbApartment = Int(NbApartment)!
})
// complet
self._REF_BASE.child("Post").child("\(postiiD)/Amenities").observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
let LiftAvailability = value?["LiftAvailability"] as? String ?? ""
let KitchenAvailability = value?["KitchenAvailability"] as? String ?? ""
let FurnitureAvailability = value?["FurnitureAvailability"] as? String ?? ""
let CarageAvailability = value?["CarageAvailability"] as? String ?? ""
let SwimmingPoolAvailability = value?["SwimmingPoolAvailability"] as? String ?? ""
let ParkingAvailability = value?["ParkingAvailability"] as? String
let FiberOpticAvailability = value?["FiberOpticAvailability"] as? String
let FireplaceAvailability = value?["FireplaceAvailability"] as? String
let DiningroomAvailability = value?["DiningroomAvailability"] as? String
let LaundryAvailability = value?["LaundryAvailability"] as? String
let CentralAirAvailability = value?["CentralAirAvailability"] as? String
let BalconyAvailability = value?["BalconyAvailability"] as? String
let MaidRoomAvailability = value?["MaidRoomAvailability"] as? String
let DriverRoomAvailability = value?["DriverRoomAvailability"] as? String
let InternalStairAvailability = value?["InternalStairAvailability"] as? String
let BasementAvailability = value?["BasementAvailability"] as? String
})
arrpost.append(p)
}
}
func updateHomeView(post : Post){
totalPriceLb.text = "\(String(post.TotalPrice)) SR"
areaLb.text = String(post.Area)
AddressLb.text = "\(post.City) \(post.District) \(post.Street)"
imageName.image = UIImage(named: "HomePic.jpg")
if post.PropertyType == "Home" {
bathLb.text = String(post.NbBathroom)
BedLb.text = String(post.NbBedroom)
imageName.image = UIImage(named: "HomePic.jpg")
}else if post.PropertyType == "Apartment" {
bathLb.text = String(post.NbBathroom)
BedLb.text = String(post.NbBedroom)
imageName.image = UIImage(named: "ApartPic.jpg")
}else if post.PropertyType == "Land"{
bathLb.isHidden = true
BedLb.isHidden = true
imageName.image = UIImage(named: "LandPic.jpg")
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
DataService.instance.retPost2()
// tableView.reloadData()
return DataService.instance.arrpost.count
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
}
func tableView
(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell") as! homecell
let post = DataService.instance.arrpost[indexPath.row]
// let post = DataServiceTemp.instance.getPosts()[indexPath.row]
cell.updateHomeView(post: post)
// tableView.reloadData()
return cell
}
I have a problem in my IOS App. I'm Using Firebase for saving & Retrieving data. All connections are good and the data is retrieved fine or sometimes incomplete.
And My Problem is when I run the app the views, labels, Pictures, etc are shown Empty at first when this components should show the data retrieved from firebase. I don't know what's the problem. Is it time or anything else? So the main problem is the components are shown empty before retrieving the data completely. I want to force the app to not show empty at first but showing the components with data.
I already use all method from google
https://firebase.google.com/docs/database/ios/read-and-write

Make hover UIView above the mainVC with a UIActivityIndicator until response comes from Firebase remove it

Related

Fetch new comments from firebase using a query

I have a handleRefresh() function that is called when the user refreshes the page. When the refresh happens new comments that were posted are loaded into the tableview.
The problem i have is that when the users refreshes the data in the tableview loads twice so i get the updated comments but with duplicates where it has reloaded the old comments again.
I am a bit stuck on how to fix this.
Here is the code.
var CommentsQuery: DatabaseQuery {
let postRef = Database.database().reference().child("posts")
let postKey = keyFound
let postCommentRef = postRef.child(postKey)
let lastComment = self.comments.last
var queryRef: DatabaseQuery
if lastComment == nil {
queryRef = postCommentRef.queryOrdered(byChild: "timestamp")
} else {
let lastTimestamp = lastComment!.createdAt.timeIntervalSince1970 * 1000
queryRef = postCommentRef.queryOrdered(byChild: "timestamp").queryEnding(atValue: lastTimestamp)
}
return queryRef
}
#objc func handleRefresh() {
CommentsQuery.queryLimited(toLast: 20).observeSingleEvent(of: .value) { snapshot in
var tempComments = [Comments]()
let commentsSnap = snapshot.childSnapshot(forPath: "comments")
let allComments = commentsSnap.children.allObjects as! [DataSnapshot]
for commentSnap in allComments {
let degree = commentSnap.childSnapshot(forPath: "reply degree").value as? String ?? ""
let name = commentSnap.childSnapshot(forPath: "reply name").value as? String ?? ""
let text = commentSnap.childSnapshot(forPath: "reply text").value as? String ?? ""
let university = commentSnap.childSnapshot(forPath: "reply university").value as? String ?? ""
let photoURL = commentSnap.childSnapshot(forPath: "reply url").value as? String ?? ""
let url = URL(string: photoURL)
let timestamp = commentSnap.childSnapshot(forPath: "timestamp").value as? Double
let lastComment = self.comments.last
if snapshot.key == lastComment?.id {
let newComments = Comments(id: snapshot.key, fullname: name, commentText: text, university: university, degree: degree, photoURL: photoURL, url: url!, timestamp: timestamp!)
tempComments.insert(newComments, at: 0)
print("fetchRefresh")
}
}
self.comments.insert(contentsOf: tempComments, at: 0)
self.fetchingMore = false
self.refreshControl.endRefreshing()
self.tableView.reloadData()
}
}
If the self.comments.last is persisted across page reloads, then it seems to be that the problem is that you use queryEnding(atValue: here:
queryRef = postCommentRef.queryOrdered(byChild: "timestamp").queryEnding(atValue: lastTimestamp)
Since timestamp values are incremental (higher values are newer), you want the node with a timestamp higher than the latest value, which you do with queryStarting(atValue: and not with queryEnding(atValue:.

How to Clear Shared Dictionary which is causing saved values not to clear even when I login with other user

How can I clear the shared dictionary on logout in which I am saving login response?
Here is the code I am doing on getting status 1.
if(status == 1)
{
DispatchQueue.main.async {
GAReusableClass.sharedInstance.hideActivityIndicator()
UserDefaults.standard.set(self.DataDict, forKey:MaindataKey)
let Dict = self.mainDict[KData] as! [String: AnyObject]
print("self.DataDict", self.DataDict)
let User_ID = Dict[KUuid]as! String
print(User_ID)
let HMACSECRETKEY = self.deviceToken + "+" + User_ID
kHMACKey = HMACSECRETKEY
let cipher:String = CryptoHelper.encrypt(input:HMACSECRETKEY)!;
print(HMACSECRETKEY)
UserDefaults.standard.setValue(cipher, forKey:HmacKey)
UserDefaults.standard.set(true, forKey: "isLogin")
GAloginUserInfo.shared.saveUserInfo(dict: Dict )
let tabar = self.storyboard?.instantiateViewController(withIdentifier: "GAtHomeTabbarViewController") as! GAtHomeTabbarViewController
self.navigationController?.pushViewController(tabar, animated: true)
}
Here is the shared dictionary which I am using to save the values of login response.
import UIKit
import Firebase
class GAloginUserInfo: NSObject {
var loginUserMobileNo : String?
var loginUserId : String?
var loginUserUuid : String?
var loginUserCountry : String?
var loginUserCountryCode : String?
var loginUserEmail : String?
var loginUserlatitude : String?
var loginUserLongitude : String?
var loginUserName : String?
var loginUserQrcode : String?
var loginUserProfilePic : String?
var isverify : String?
var loginPassword : String?
var dateOfBirth: String?
var earnedPoints:String?
var loginUserGender:String?
var loginUserFollowers:Int = 0
static let shared = GAloginUserInfo()
func saveUserInfo (dict : [String : AnyObject?] ) {
if let loginUserMobileNo = dict["mobile"] as? String {
self.loginUserMobileNo = loginUserMobileNo
}
if let loginUserId = dict["id"] as? String {
self.loginUserId = loginUserId
}
if let loginUserUuid = dict["uuid"] as? String {
self.loginUserUuid = loginUserUuid
print(loginUserUuid)
}
if let loginUserCountry = dict["country"] as? String {
self.loginUserCountry = loginUserCountry
}
if let loginUserCountryCode = dict["country_code"] as? String {
self.loginUserCountryCode = loginUserCountryCode
}
if let loginUserEmail = dict["email"] as? String {
self.loginUserEmail = loginUserEmail
}
if let loginUserProfilePic = dict["profile_pic"] as? String {
self.loginUserProfilePic = loginUserProfilePic
}
if let loginUserLongitude = dict["logitude"] as? String {
self.loginUserLongitude = loginUserLongitude
}
if let loginUserName = dict["name"] as? String {
self.loginUserName = loginUserName
}
if let loginUserQrcode = dict["qr_code"] as? String {
self.loginUserQrcode = loginUserQrcode
}
if let Password = dict["password"] as? String{
self.loginPassword = Password
}
if let dateOfBirth = dict["dob"] as? String{
self.dateOfBirth = dateOfBirth
}
if let earnedPoints = dict["points"] as? String{
let myDouble = Double(earnedPoints)
let doubleStr = String(format: "%.2f", myDouble!)
self.earnedPoints = doubleStr
}
if let loginUserGender = dict["gender"] as? String{
self.loginUserGender = loginUserGender
}
if let loginUserFollowers = dict["followersCount"] as? Int{
self.loginUserFollowers = loginUserFollowers
}
}
}
Actually, the problem is when I log out and log in again with some other user it still shows some values of the previous user. I am clearing the userdefaults on the logout function. but I don't know how to clear this type of shared dictionary.
Use removeObject(forKey:)
to remove the values stored from user defaults in Logout method
UserDefaults.standard.removeObject(forKey: MaindataKey)
UserDefaults.standard.removeObject(forKey: HmacKey)
UserDefaults.standard.set(false, forKey: "isLogin")
Create a method to remove the values from the singleton class like this
extension GAloginUserInfo {
func removeUserInfo() {
self.loginUserMobileNo = nil
self.loginUserId = nil
self.loginUserUuid = nil
self.loginUserCountry = nil
self.loginUserCountryCode = nil
self.loginUserEmail = nil
self.loginUserlatitude = nil
self.loginUserLongitude = nil
self.loginUserName = nil
self.loginUserQrcode = nil
self.loginUserProfilePic = nil
self.isverify = nil
self.loginPassword = nil
self.dateOfBirth = nil
self.earnedPoints = nil
self.loginUserGender = nil
self.loginUserFollowers = 0
}
}
and call this method in logout
GAloginUserInfo.shared.removeUserInfo()

How to connect to new viewController with data saved in struct model of other viewController

How can I get the data that in Struct model in new viewController
I got a viewController when i print the var in Struct model it appeare just fine.
I created New viewController trying to get the same data in otherview of that struct model but when i print it it give me nil
I tryied to make the model equal to the new model in the new viewController
MessageController View
var messages = [Message]()
var users = [Contact]()
var messagesDicionary = [String: Message]()
var testMSG : Message?
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let message = self.messages[indexPath.row]
let chatPartnerId = message.chatPartnerId()
let ref = Database.database().reference().child("users").child(chatPartnerId)
ref.observe(.value) { (snap) in
if let dictinoary = snap.value as? [String: AnyObject] {
guard let email = dictinoary["email"] ,let profileimage = dictinoary["profileimage"], let userid = dictinoary["userid"], let username = dictinoary["username"] else {
return
}
var user = Contact()
user.userid = chatPartnerId
user.userid = chatPartnerId
let userValue = Contact.init(email: email as? String, username: username as? String, profileimage: profileimage as? String, userid: userid as? String)
self.users.append(userValue)
self.showChatControllerToUser(user: userValue)
print(message.receivername)
}
}
}
result of Print Optional("Omar")
ChatMessagesController View
var user :Contact?
var users = [Contact]()
var message: Message?
var messagesArray = [Message]()
func observeChatMessages() {
guard let uid = Auth.auth().currentUser?.uid else {
return
}
let userMessagesRef = Database.database().reference().child("usersmesssages").child(uid)
userMessagesRef.observe(.childAdded) { (snap) in
let messageId = snap.key
let messageRef = Database.database().reference().child("messages").child(messageId)
messageRef.observeSingleEvent(of: .value, with: { (snapshot) in
guard let dictionary = snapshot.value as? [String:AnyObject] else {
return
}
let text = dictionary["text"] as? String
let receiverid = dictionary["receiverid"] as? String
let senderid = dictionary["senderid"] as? String
let time = dictionary["timestamp"] as? TimeInterval
let senderName = dictionary["sendername"] as? String
let receiverName = dictionary["receivername"] as? String
self.messagesArray.append(MessageValue)
self.chatTableView.reloadData()
print(self.message?.receivername)
})
}
}
result of print NIL
Message Model
struct Message {
var text: String?
var receiverid: String?
var senderid: String?
var timestamp: TimeInterval?
var sendername: String?
var receivername: String?
func chatPartnerId() -> String {
return (senderid == Auth.auth().currentUser?.uid ? receiverid : senderid)!
}
}
I tried to make in MessagesController
let chatMessage = ChatMessageController()
chatMessage.message = self.testMSG

UITableView Null Value

I have a list of JSON data downloaded from server:
(DataModal.swift)
class DataModal {
var orderAutoid: Int?
var orderId: String?
var orderName: String?
var orderQty: String?
var orderStatus: String?
init(bOrder_autoid: Int, bOrder_id: String, bOrder_name: String, bOrder_qty: String, bOrder_status: String){
self.orderAutoid = bOrder_autoid
self.orderId = bOrder_id
self.orderName = bOrder_name
self.orderQty = bOrder_qty
self.orderStatus = bOrder_status
}
(OrderStructureDownloadProtocol.swift)
protocol OrderStructureDownloadProtocol: class {
func newItemDownload(items: Array<Any>)
}
....
var jsonElement = Dictionary<String, Any>()
var newOrders = Array<Any>()
for i in 0..<jsonResult.count {
jsonElement = jsonResult[i] as! Dictionary
let newOrder_autoid = jsonElement["orderAutoid"] as? Int ?? 0
let newOrder_id = jsonElement["orderId"] as? String ?? ""
let newOrder_name = jsonElement["orderName"] as? String ?? ""
let newOrder_qty = jsonElement["orderQty"] as? String ?? ""
let newOrder_status = jsonElement["orderStatus"] as? String ?? ""
let newOrder = BMSDataModal(bOrder_autoid: newOrder_autoid, bOrder_id: newOrder_id, bOrder_name: newOrder_name, bOrder_qty: newOrder_qty, bOrder_status: newOrder_status)
newOrders.append(newOrder)
}
DispatchQueue.main.async (
execute: { () -> Void in
self.delegate.newItemDownload(items: newOrders as! Array<Any>)
})
(tableview.swift)
var newOrdersArray = [BMSDataModal]()
func newItemDownload(items: Array<Any>) {
newOrdersArray = items as! [BMSDataModal]
newOrderLookupTableView.reloadData()
}
(tableview.swift another part)
let cell = tableView.dequeueReusableCell(withIdentifier: "orderLookupCell", for: indexPath) as! NewOrderTableViewCell
let item = newOrdersArray[indexPath.row]
cell.newHMNumber?.text = item.orderId ?? "-"
cell.newMP?.text = item.orderName ?? "-"
cell.newQTY?.text = item.orderQty ?? "-"
return cell
}
having all the old NS-style changed. The app is running okay, there are some items that need to reset. As my data-source always contain Double, but I declared it as a String, as I won't deal with calculation so I treated it as 'String'.

Instance method takes long time for type-cheking

I have quite a big project that takes a long time to compile. When I checked compilation times of methods. I found that this method, for example, takes usually more than 200ms to compile. What can I do to improve this?
func processSnapshot(snapshot:DataSnapshot) {
self.numberOfUsers.text = "#Total DB (users): \(snapshot.childrenCount.description)"
for child in snapshot.children {
if let snapshot = child as? DataSnapshot,
let userProfile = UserProfile(snapshot: snapshot) {
if userProfile.picUrl == "" {
numberOfUsersWithOutPicUrl += 1
}
let todayLong = "\(Date())".prefix(10)
if userProfile.createdOnLong.prefix(10) == todayLong {
profileWizardsStartedTotday += 1
if userProfile.weight != "" {
profileWizardsCompletedTotday += 1
}
}
profiles.append(userProfile)
}
}
let numberOfUsersWithOutPicUrlPercent = round(Double(numberOfUsersWithOutPicUrl)*100/Double(numberOfRealUsers))
let sizeOfSnapshotValueInKB:Int = String(describing: snapshot.value).count / 1024
self.userThatAbortedOnBoarding.text = numberOfUsersWithOutPicUrl.description
self.userThatAbortedOnBoardingPercent.text = "\(numberOfUsersWithOutPicUrlPercent)%"
self.userThatStartedOnBoardingToday.text = profileWizardsStartedTotday.description
self.userThatCompletedOnBoardingToday.text = profileWizardsCompletedTotday.description
self.sizeOfSnapshot.text = "\(sizeOfSnapshotValueInKB.description)KB"
}
My UserProfile initializer looks like this:
init?(snapshot: DataSnapshot) {
print("\(snapshot.key) - \(String(describing: snapshot.value))")
guard
let value = snapshot.value as? [String: AnyObject],
let uid = value["uid"] as? String
else {
print("Warning: Userprofile has no UID")
return nil
}
self.uid = uid
self.email = value["email"] as? String ?? ""
self.picUrl = value["picurl"] as? String ?? ""
self.picUrl2 = value["picurl2"] as? String ?? ""
self.picUrl3 = value["picurl3"] as? String ?? ""
self.picUrl4 = value["picurl4"] as? String ?? ""
self.picUrl5 = value["picurl5"] as? String ?? ""
self.picUrl6 = value["picurl6"] as? String ?? ""
self.city = value["city"] as? String ?? ""
self.displayName = value["displayName"] as? String ?? "anonymous"
}