Posts

Post marked as solved
6 Replies
OK, I had to think about this one more time and i finally got it working 100%. Aside from the call to get all the user documents, I was making another call at the same time to the collection that was storing the values for isOnline. I added isOnline to the members model and a separate snapshot listener to monitor the changes to that key. Now everything is working 100%. Hope this helps anyone. I have updated my code: Service Class **This function is to update the user's presence when online or not and it's called inside SceneDelegate **  static func isUserOnline(bool: Bool) {     guard let currentUID = Auth.auth().currentUser?.uid else { return }           if !currentUID.isEmpty {       let dictionary = [USER_IS_ONLINE: bool as Any,              USER_LASTEST_ONLINE: Date().timeIntervalSince1970 as Any]               USERS_COLLECTION.document(currentUID).getDocument { (document, error) in         if let error = error {           print("Error..\(error.localizedDescription)")         } else {           if document?.exists == true {             USERS_COLLECTION.document(currentUID).updateData(dictionary)           } else {             USERS_COLLECTION.document(currentUID).updateData(dictionary)           }}}}} **SceneDelegate** func sceneDidDisconnect(_ scene: UIScene) {     Service.isUserOnline(bool: false)   }   func sceneDidBecomeActive(_ scene: UIScene) {     Service.isUserOnline(bool: true)   }   func sceneWillResignActive(_ scene: UIScene) {     Service.isUserOnline(bool: false)   }   func sceneDidEnterBackground(_ scene: UIScene) {     Service.isUserOnline(bool: false)   } **This function is to monitor the user activity**       static func checkUserOnlineStatus(with userId: String, completion: @escaping(Bool) -> Void) {     let query = USERS_COLLECTION.document(userId)           query.getDocument { (document, error) in       if let document = document, document.exists {         let isOnline = document.get(USER_IS_ONLINE) as? Bool ?? false         completion(isOnline)       }     }     query.addSnapshotListener { (document, error) in       if let document = document, document.exists {         let isOnline = document.get(USER_IS_ONLINE) as? Bool ?? false         completion(isOnline)       }}} Calling the function inside the cell class func configureHomeFeedCell(member: Member) {  Service.checkUserOnlineStatus(with: member.documentId) { isOnline in       self.onlineViewStatus.backgroundColor = isOnline == true ? .green : .red     } }
Post marked as solved
6 Replies
Thank you for the last suggestion, I ended moving the function from the cell class to the view controller and called it inside cellForRowAt, so far, it's working as expected. Here is the updated code: func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {     let hCell = homeFeedTableView.dequeueReusableCell(withIdentifier: "HomeFeedCell", for: indexPath) as! HomeFeedCell           hCell.selectionStyle = .none     hCell.backgroundColor = UIColor.white           if !members.isEmpty {       hCell.configureHomeFeedCell(member: self.members[indexPath.row])       checkUserOnlineStatus(with: members[indexPath.row].documentId) { isOnline in         hCell.onlineViewStatus.backgroundColor = isOnline == true ? .green : .red       }     }     return hCell   }           func checkUserOnlineStatus(with userId: String, completion: @escaping(Bool) -> Void) {     let query = USERS_COLLECTION.document(userId).collection(IS_ONLINE)     query.getDocuments { (snapshot, error) in       if let error = error {         print("ERROR..\(error.localizedDescription)")       } else {         snapshot?.documents.forEach({ diff in           let isOnline = diff.get(USER_IS_ONLINE) as? Bool           completion(isOnline!)         })}}       query.addSnapshotListener { (snapshot, error) in         snapshot?.documentChanges.forEach { diff in           let isOnline = diff.document.get(USER_IS_ONLINE) as? Bool           if (diff.type == .modified) {             completion(isOnline!)           }}}   }
Post marked as solved
6 Replies
Thank you Scott, yes, I was thinking on moving the function to the view controller, but, i need to add a delegate for the onlineViewStatus UIView as this is inside the cell.
Post marked as solved
12 Replies
You were correct, after delaying the dismissal of the view controllers by 2 seconds, the table view is refreshed with no issues. To transition back to the MemberListVC I was using "unWind" but the problem there is that as soon as you press the button, it jumps back to the initial VC and there was no time for the async call to finish. So what I end up doing is adding the 2 seconds delay (it shows a loader while is running) and calling the returnToInitialVC() function, this function removes the 2 views from the stack. Thank you for your time! DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {         self.returnToInitialVC()         self.showLoader(false)       } func returnToInitialVC() {     let viewControllers: [UIViewController] = self.navigationController!.viewControllers as [UIViewController]     self.navigationController!.popToViewController(viewControllers[viewControllers.count - 3], animated: true)   }
Post marked as solved
12 Replies
User is blocked in alert action, once done that MemberVC is dismissed and app goes to MemberListVC. Let's say in MemberListVC you have 3 users, you open one of the profiles with MemberVC and then you block the user. When the app goes back to the MemberListVC, there should be 2 users only. I'm going to do a test delaying the dismissal to MemberListVC, let's see if that gives time for the async call to finish and the table view reloads properly.
Post marked as solved
12 Replies
The goal of that statement is to remove the user that is logged in when I'm filtering the array. As mentioned, that section works properly, the issue I'm having is reloading/refreshing the table view when i go back to MemberListVC. Is viewDidAppear or viewWillAppear OK to use to reload/refresh the table view?
Post marked as solved
12 Replies
To load the array inside ViewDidLoad in calling this function "fetchUsers()". Inside this block lastDocument is included. And userDefaults is loaded in the MemberVC right after the user block is called. func fetchUsers() {     if lastDocument == nil {       let query = MATCH_INFO_COLLECTION.document(currentUID!)         .collection("info").order(by: MATCH_TIMESTAMP, descending: false)               query.limit(to: 10).getDocuments { (snapshot, error) in                        self.filterUsersThatWereBlocked { blockedUsers in                                   guard let last = snapshot?.documents.last else { return }                 guard let snap = snapshot else { return }                 snap.documents.forEach({ document in                                       let data = document.data()                   let memberId = data[DOCUMENT_ID] as? String ?? ""                   let memberAge = data[AGE] as? Int ?? 0                   let memberName = data[FIRST_NAME] as? String ?? ""                   let memberImageUrl = data[PROFILE_IMAGE_URL] as? String ?? ""                   let memberCurrentCity = data[CURRENT_CITY] as? String ?? ""                   let timestamp = data[TIMESTAMP] as? Double ?? 0.0                                       let matches = Match(memberId: memberId, memberAge: memberAge ,memberName: memberName, memberImageUrl: memberImageUrl, memberCurrentCity: memberCurrentCity, timestamp: Date(timeIntervalSince1970: timestamp))                                       guard matches.memberId != Auth.auth().currentUser?.uid else { return }                                       guard blockedUsers[matches.memberId] == nil else { return }                                       self.match.append(matches)                                                           self.matchedMessagesTV.reloadData()                 })                 self.lastDocument = last               }}     } else {       matchedMessagesTV.tableFooterView = createSpinnerFooter()       let query = MATCH_INFO_COLLECTION.document(currentUID!)         .collection("info").order(by: MATCH_TIMESTAMP, descending: false)               query.start(afterDocument: lastDocument!)         .limit(to: 10).getDocuments { (snapshot, error) in                         self.filterUsersThatWereBlocked { blockedUsers in                   DispatchQueue.main.async {                     self.matchedMessagesTV.tableFooterView = nil                   }                   guard let last = snapshot?.documents.last else { return }                   guard let snap = snapshot else { return }                                       snap.documents.forEach({ document in                                           let data = document.data()                     let memberId = data[DOCUMENT_ID] as? String ?? ""                     let memberAge = data[AGE] as? Int ?? 0                     let memberName = data[FIRST_NAME] as? String ?? ""                     let memberImageUrl = data[PROFILE_IMAGE_URL] as? String ?? ""                     let memberCurrentCity = data[CURRENT_CITY] as? String ?? ""                     let timestamp = data[TIMESTAMP] as? Double ?? 0.0                                           let matches = Match(memberId: memberId, memberAge: memberAge ,memberName: memberName, memberImageUrl: memberImageUrl, memberCurrentCity: memberCurrentCity, timestamp: Date(timeIntervalSince1970: timestamp))                                           guard matches.memberId != Auth.auth().currentUser?.uid else { return }                                           guard blockedUsers[matches.memberId] == nil else { return }                                           self.match.append(matches)                                                           self.matchedMessagesTV.reloadData()                   })                   self.lastDocument = last                 }}}   }
Post marked as solved
12 Replies
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {          return match.count   } class Match {       let memberId: String   let memberAge: Int   let memberName: String   let memberImageUrl: String   let memberCurrentCity: String   let timestamp: Date!       init(memberId: String, memberAge: Int, memberName: String, memberImageUrl: String, memberCurrentCity: String, timestamp: Date) {           self.memberId = memberId     self.memberAge = memberAge     self.memberName = memberName     self.memberImageUrl = memberImageUrl     self.memberCurrentCity = memberCurrentCity     self.timestamp = timestamp   } } and these are the properties in the main VC: var match = [Match]()   var lastDocument: DocumentSnapshot? = nil   let userDefaults = UserDefaults.standard
Post marked as solved
12 Replies
Per your request: func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {     let tvCell = matchedMessagesTV.dequeueReusableCell(withIdentifier: "MatchedMessagesCell", for: indexPath) as! MatchedMessagesCell     tvCell.configureMatchedMessagesCell(match: match[indexPath.row])           tvCell.selectionStyle = .none     tvCell.backgroundColor = .beige           tvCell.profileImageBlur.isHidden = true     tvCell.profileNameBlur.isHidden = true     tvCell.profileCityBlur.isHidden = true     tvCell.timeStampBlur.isHidden = true     tvCell.matchAvailableLbl.isHidden = true           if indexPath.row >= 2 {       tvCell.profileImageBlur.isHidden = false       tvCell.profileNameBlur.isHidden = false       tvCell.profileCityBlur.isHidden = false       tvCell.timeStampBlur.isHidden = false       tvCell.matchAvailableLbl.isHidden = false     }     return tvCell   } and here is the cell class: class MatchedMessagesCell: UITableViewCell {       @IBOutlet weak var profileImage: UIImageView!   @IBOutlet weak var profileNameLbl: UILabel!   @IBOutlet weak var profileCityLbl: UILabel!   @IBOutlet weak var timeStampLbl: UILabel!   @IBOutlet weak var profileImageBlur: UIVisualEffectView!   @IBOutlet weak var profileCityBlur: UIVisualEffectView!   @IBOutlet weak var profileNameBlur: UIVisualEffectView!   @IBOutlet weak var timeStampBlur: UIVisualEffectView!       func configureMatchedMessagesCell(match: Match) {           profileImage.loadImage(with: match.memberImageUrl)     profileNameLbl.text = match.memberName + "(" + "\(match.memberAge)" + ")"     profileCityLbl.text = match.memberCurrentCity     timeStampLbl.text = match.timestamp.timeAgoToDisplay()   } }
Post marked as solved
3 Replies
func fetchGlimpseData() {       if lastDocument == nil {         GLIMPSE_ALL_USERS_DATA.order(by: TIMESTAMP, descending: true).limit(to: 3)           .getDocuments { [self] (snapshot, error) in           guard let last = snapshot?.documents.last else { return }             for dictionary in snapshot!.documents {                            let name = dictionary[FIRST_NAME] as? String ?? ""             let age = dictionary[AGE] as? String ?? ""             let city = dictionary[CURRENT_CITY] as? String ?? ""             let profileImageURL = dictionary[PROFILE_IMAGE_URL] as? String ?? ""             let glimpseCaption = dictionary[GLIMPSE_CAPTION] as? String ?? ""             let glimpseURL = dictionary[GLIMPSE_IMAGE_URL] as? String ?? ""             let timestamp = dictionary[TIMESTAMP] as? Double ?? 0.0             let documentID = dictionary.documentID                           let glimpseInfo = Glimpse(name: name, age: age, city: city, profileImageURL: profileImageURL, glimpseCaption: glimpseCaption, glimpseURL: glimpseURL, timestamp: Date(timeIntervalSince1970: timestamp), documentID: documentID)                               self.glimpse.append(glimpseInfo)               self.glimpseTableView.reloadData()             }           self.lastDocument = last         }       } else {         glimpseTableView.tableFooterView = createSpinnerFooter()                   GLIMPSE_ALL_USERS_DATA.order(by: TIMESTAMP, descending: true).start(afterDocument: lastDocument!).limit(to: 3)           .getDocuments { [self] (snapshot, error ) in                           DispatchQueue.main.async {               self.glimpseTableView.tableFooterView = nil             }                           guard let last = snapshot?.documents.last else { return }             for dictionary in snapshot!.documents {             let name = dictionary[FIRST_NAME] as? String ?? ""             let age = dictionary[AGE] as? String ?? ""             let city = dictionary[CURRENT_CITY] as? String ?? ""             let profileImageURL = dictionary[PROFILE_IMAGE_URL] as? String ?? ""             let glimpseCaption = dictionary[GLIMPSE_CAPTION] as? String ?? ""             let glimpseURL = dictionary[GLIMPSE_IMAGE_URL] as? String ?? ""             let timestamp = dictionary[TIMESTAMP] as? Double ?? 0.0             let documentID = dictionary.documentID             let glimpseInfo = Glimpse(name: name, age: age, city: city, profileImageURL: profileImageURL, glimpseCaption: glimpseCaption, glimpseURL: glimpseURL, timestamp: Date(timeIntervalSince1970: timestamp), documentID: documentID)               self.glimpse.append(glimpseInfo)               self.glimpseTableView.reloadData()             }             self.lastDocument = last         }}     } //This is what i use to delete the post func optionsMenu(sendUser: String) {           let alert = UIAlertController(title: "MyApp", message: "Options", preferredStyle: .actionSheet)     alert.view.tintColor = .brick           let deleteGlimpse = UIAlertAction(title: "Delete Post", style: .default) { (action) in       GLIMPSE_USER_COLLECTION.delete() { err in         if let err = err {           print("COULD NOT REMOVE GLIMPSE...\(err.localizedDescription)")         } else {           print("IMG HAS BEEN DELETED")         }}       GLIMPSE_USER_STORAGE.delete()       self.handleRefresh()     }           let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: nil)     alert.addAction(deleteGlimpse)     alert.addAction(cancelAction)           if let popoverController = alert.popoverPresentationController {       popoverController.sourceView = self.view       popoverController.backgroundColor = .green       popoverController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)       popoverController.permittedArrowDirections = []     }     self.present(alert, animated: true, completion: nil)   }
Post not yet marked as solved
2 Replies
I was able to find a solution for this. Here is the updated code: func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) - Int {     return array.count   }       func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) - UITableViewCell {     let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomTableViewCell     cell.cellLbl?.text = array[indexPath.row]           cell.blurView.isHidden = true     if indexPath.row = 5 {               cell.blurView.isHidden = false     }     return cell   }
Post not yet marked as solved
6 Replies
made the changes as suggested and still does not work. Not sure what else to do. Here are 2 screenshots showing the following: Screenshot 1: 3 items that start with "in" Screenshot 2: results that only show 2 items instead of 3 dropbox link: https://www.dropbox.com/sh/ow5g7d84gk2ocwo/AADTJhdBxNwgzcl_3hoZTNY2a?dl=0 I have an item that starts with L (lower case) if I type the first letter, something else comes out.
Post not yet marked as solved
6 Replies
sorry, forgot to add the updated code: func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {     searchBar.autocapitalizationType = .none     let searchText = searchBar.text!.lowercased()     if searchText.isEmpty || searchText == " " {       inSearchMode = false       chargesTableView.reloadData()     } else {       inSearchMode = true               filteredCharges = chargesClassFromCell.filter{ searchResult in         return searchResult.chargeDescription.lowercased().hasPrefix(searchText.lowercased())       }               chargesTableView.reloadData()     }   }
Post not yet marked as solved
6 Replies
Did a test with everything lower case and everything upper case, the results are the same as described above.
Post not yet marked as solved
6 Replies
Hi, thank you for your comment. Example, I know I have 2 strings that start with "Inj", when i type that, I don't get those entries and I get 3 records and 1 of them have "inj" but somewhere in the middle. (e.g. Admin vacc pneumonia injection). Is it possible to filter upper and lower case or should I just go with upper case? thank you