I'm working on a chat app and I configured a function to check if a user is online. I'm able to see if another user is active or not, but, the issue I'm having is that if I scroll down (I'm using a UITableView) other users show as active and they are not. I placed the code inside the UITableViewCell class. Any suggestions as to what could be the problem are greatly appreciated. Here is my code:
UITableViewCell
`func configureHomeFeedCell(member: Member) {
profileImage.loadImage(with: member.imageURL)
profileName.text = "\(member.name)" + ", " + "\(member.age)"
checkUserOnlineStatus(with: member.documentId) { _ in }
}
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
self.onlineViewStatus.backgroundColor = isOnline == true ? .green : .red
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) {
self.onlineViewStatus.backgroundColor = isOnline == true ? .green : .red
completion(isOnline!)
}}}
}`
Post not yet marked as solved
Hi, I'm having a problem when opening a push notification to a specific tab when the app is closed/killed. The code below works properly when the app is in the background or in another tab. If closed and I open the push notification, the app opens to the main screen. Any ideas on how can I get it to open to the correct tab when is completely closed? any help is greatly appreciated.
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
let scene = UIApplication.shared.connectedScenes.first
if let sceneDelegate = scene?.delegate as? SceneDelegate {
if let tabController = sceneDelegate.window?.rootViewController as? UITabBarController {
tabController.selectedIndex = 1
}
}
}
Post not yet marked as solved
Hello, I'm working on this chat app and I have a snapshot listener to keep track the number of messages (with a badge) each user receives. I'm using a table view with pagination. The problem I'm having that I can't figure out is when a user gets a message, the table view duplicates the user, increases the badge number every time a message is received. Then, if i open the messages and then i go back to the first VC, there is another duplicate of the user but with no badge number because it was cleared. Any help is greatly appreciated.
VC
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
fetchMatches()
}
func fetchMatches() {
fetchInfo { matches in
self.match = matches
self.matchedMessagesTV.reloadData()
}
}
func fetchInfo(completion: @escaping([Match]) -> Void) {
if lastDocument == nil {
let query = MATCH_INFO_COLLECTION.document(currentUID!)
.collection("info").order(by: MATCH_TIMESTAMP, descending: false)
query.limit(to: 10).addSnapshotListener { (snapshot, error) in
guard let last = snapshot?.documents.last else { return }
guard let snap = snapshot else { return }
snap.documentChanges.forEach({ diff in
let dictionary = diff.document.data()
let memberId = dictionary[DOCUMENT_ID] as? String ?? ""
let memberAge = dictionary[AGE] as? Int ?? 0
let memberName = dictionary[FIRST_NAME] as? String ?? ""
let memberImageUrl = dictionary[PROFILE_IMAGE_URL] as? String ?? ""
let memberCurrentCity = dictionary[CURRENT_CITY] as? String ?? ""
let matchTimestamp = dictionary[MATCH_TIMESTAMP] as? Double ?? 0.0
let messageCounter = dictionary[MESSAGE_COUNTER] as? Int ?? 0
let matches = Match(memberId: memberId, memberAge: memberAge ,memberName: memberName, memberImageUrl: memberImageUrl, memberCurrentCity: memberCurrentCity, matchTimestamp: Date(timeIntervalSince1970: matchTimestamp), messageCounter: messageCounter)
self.match.append(matches)
self.memberId = matches.memberId
self.lastDocument = last
completion(self.match)
})
}
} else {
matchedMessagesTV.tableFooterView = createSpinnerFooter()
let query = MATCH_INFO_COLLECTION.document(currentUID!)
.collection("info").order(by: MATCH_TIMESTAMP, descending: false)
DispatchQueue.main.async {
self.matchedMessagesTV.tableFooterView = nil
}
query.start(afterDocument: self.lastDocument!)
.limit(to: 10).addSnapshotListener { (snapshot, error) in
guard let last = snapshot?.documents.last else { return }
guard let snap = snapshot else { return }
snap.documentChanges.forEach({ diff in
let dictionary = diff.document.data()
let memberId = dictionary[DOCUMENT_ID] as? String ?? ""
let memberAge = dictionary[AGE] as? Int ?? 0
let memberName = dictionary[FIRST_NAME] as? String ?? ""
let memberImageUrl = dictionary[PROFILE_IMAGE_URL] as? String ?? ""
let memberCurrentCity = dictionary[CURRENT_CITY] as? String ?? ""
let matchTimestamp = dictionary[MATCH_TIMESTAMP] as? Double ?? 0.0
let messageCounter = dictionary[MESSAGE_COUNTER] as? Int ?? 0
let matches = Match(memberId: memberId, memberAge: memberAge ,memberName: memberName, memberImageUrl: memberImageUrl, memberCurrentCity: memberCurrentCity, matchTimestamp: Date(timeIntervalSince1970: matchTimestamp), messageCounter: messageCounter)
self.match.append(matches)
self.memberId = matches.memberId
self.lastDocument = last
completion(self.match)
})
}}
}
class Match {
var memberId: String
let memberAge: Int
let memberName: String
let memberImageUrl: String
let memberCurrentCity: String
let matchTimestamp: Date!
let messageCounter: Int
init(memberId: String, memberAge: Int, memberName: String, memberImageUrl: String, memberCurrentCity: String, matchTimestamp: Date, messageCounter: Int) {
self.memberId = memberId
self.memberAge = memberAge
self.memberName = memberName
self.memberImageUrl = memberImageUrl
self.memberCurrentCity = memberCurrentCity
self.matchTimestamp = matchTimestamp
self.messageCounter = messageCounter
}
}
Post not yet marked as solved
I'm trying to replicate the image zoom in/out feature we find in IG, the only issue I'm having is when I zoom-in, the image is not covering the entire screen, it only zooms-in inside the cell. This is a regular setup, a table view, a cell, an image view and a label. I'm not sure what I'm missing here. Any help is greatly appreciated:
View Controller
import UIKit
class ViewController: UIViewController, UITableViewDelegate {
@IBOutlet weak var tableView: UITableView!
var picArray = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
tableView.rowHeight = 300
}
}
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return picArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! cell
let data = picArray[indexPath.item]
cell.backgroundColor = .red
cell.setupCell(image: data)
cell.clipsToBounds = false
cell.selectionStyle = .none
return cell
}
}
Cell Class
import UIKit
class cell: UITableViewCell, UIScrollViewDelegate {
@IBOutlet var picture: UIImageView!
@IBOutlet var caption: UILabel!
var zoomEnabled = false
var imgCenter:CGPoint?
override func awakeFromNib() {
super.awakeFromNib()
picture.contentMode = .scaleAspectFill
picture.isUserInteractionEnabled = true
picture.clipsToBounds = false
caption.layer.zPosition = -1
let pinch = UIPinchGestureRecognizer(target: self, action: #selector(self.pinch(sender:)))
pinch.delegate = self
self.picture.addGestureRecognizer(pinch)
let pan = UIPanGestureRecognizer(target: self, action: #selector(self.pan(sender:)))
pan.delegate = self
self.picture.addGestureRecognizer(pan)
}
override func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
@objc func pan(sender: UIPanGestureRecognizer) {
if self.zoomEnabled && sender.state == .began {
self.imgCenter = sender.view?.center
} else if self.zoomEnabled && sender.state == .changed {
let translation = sender.translation(in: self)
if let view = sender.view {
view.center = CGPoint(x:view.center.x + translation.x,
y:view.center.y + translation.y)
}
sender.setTranslation(CGPoint.zero, in: self.picture.superview)
}
}
@objc func pinch(sender: UIPinchGestureRecognizer) {
if sender.state == .began {
let currentScale = self.picture.frame.size.width / self.picture.bounds.size.width
let newScale = currentScale * sender.scale
if newScale > 1 {
self.zoomEnabled = true
}
} else if sender.state == .changed {
guard let view = sender.view else {return}
let pinchCenter = CGPoint(x: sender.location(in: view).x - view.bounds.midX,
y: sender.location(in: view).y - view.bounds.midY)
let transform = view.transform.translatedBy(x: pinchCenter.x, y: pinchCenter.y)
.scaledBy(x: sender.scale, y: sender.scale)
.translatedBy(x: -pinchCenter.x, y: -pinchCenter.y)
let currentScale = self.picture.frame.size.width / self.picture.bounds.size.width
var newScale = currentScale * sender.scale
if newScale < 1 {
newScale = 1
let transform = CGAffineTransform(scaleX: newScale, y: newScale)
self.picture.transform = transform
sender.scale = 1
}else {
view.transform = transform
sender.scale = 1
}
} else if sender.state == .ended {
guard let center = self.imgCenter else {return}
UIView.animate(withDuration: 0.3, animations: {
self.picture.transform = CGAffineTransform.identity
self.picture.center = center
}, completion: { _ in
self.zoomEnabled = false
})
}
}
func setupCell(image: String) {
if let image : UIImage = UIImage(named: image) {
picture.image = image
}
}
}
Hello,
I'm working on this messaging app where users have the option of blocking other users. The problem I'm having is reloading the UITableView after a user has been blocked. The first block of code is to block the users:
MemberVC
func blockUserOption(forMember memberData: String, userHasBeenBlocked: Bool, completion: ((Error?) -> Void)?) {
BLOCKED_USERS_COLLECTION.document(currentUID!).getDocument { (snapshot, error) in
let data = [self.memberDocumentID: userHasBeenBlocked]
if snapshot?.exists == true {
BLOCKED_USERS_COLLECTION.document(self.currentUID!).updateData(data)
} else {
BLOCKED_USERS_COLLECTION.document(self.currentUID!).setData(data)
}}}
//Here is how I'm executing the code above:
let blockUser = UIAlertAction(title: "Block", style: .default) { (action) in
let alert = UIAlertController(title: "Block", message: "Are you sure you want to block" + " " + "\(self.memberName as Any)?", preferredStyle: .alert)
alert.view.tintColor = .brick
alert.addAction(UIAlertAction(title: "Yes", style: .default, handler: { (action: UIAlertAction) in
self.blockUserOption(forMember: self.memberDocumentID, userHasBeenBlocked: true, completion: nil)
self.userDefaults.setValue("yes", forKey: RELOAD)
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action: UIAlertAction!) in
}))
self.present(alert, animated: true, completion: nil)
}
Once the user has been blocked, the current view controller gets dismissed and the user goes back to the view controller where the table view needs to reload and remove the blocked user from the list.
MemberListVC
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
let reloadQuery = userDefaults.string(forKey: RELOAD)
if reloadQuery == "yes" {
self.match.removeAll()
let query = MATCH_INFO_COLLECTION.document(currentUID!)
.collection("info").order(by: 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, matchTimestamp: 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
}
}
userDefaults.setValue("no", forKey: RELOAD)
} else {
print("NOTHING TO DO HERE")
}
}
func filterUsersThatWereBlocked(completion: @escaping([String: Bool]) -> Void) {
guard let currentUid = Auth.auth().currentUser?.uid else { return }
BLOCKED_USERS_COLLECTION.document(currentUid).getDocument { (snapshot, error) in
guard let data = snapshot?.data() as? [String: Bool] else {
completion([String: Bool]())
return
}
completion(data)
}}
Now, if I close and re-open the app, the users that were blocked, do not show up. I'm not sure if the issue is because I'm trying to reload the view inside "viewDidAppear", I tried with "viewWillAppear" and the outcome is the same. Any help is greatly appreciated. Thank you!
Hello, I'm working on an app that is fetching data from Firebase and the data is loaded in a UITableView. I'm using pagination (loading 3 posts at a time). Users are allowed to delete their own post. The issue I'm having is when the user deletes the post (first from Firebase and then from the array), the tableView removes the user's post, but it also removes (from the view only) the next 2 posts. Then all I see are the next 3 posts and if I scroll up to see the previous ones, the app crashes because the indexPath.row is out of range. Below is my code. Any help is greatly appreciated:
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
fetchGlimpseData()
configureRefreshControl()
}
func configureRefreshControl() {
let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(handleRefresh), for: .valueChanged)
glimpseTableView?.refreshControl = refreshControl
}
private func createSpinnerFooter() -> UIView {
let footerView = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: 100))
let spinner = UIActivityIndicatorView()
spinner.center = footerView.center
spinner.color = .brick
footerView.addSubview(spinner)
spinner.startAnimating()
return footerView
}
@objc func handleRefresh() {
glimpse.removeAll(keepingCapacity: false)
self.currentKey = nil
fetchGlimpseData()
}
func fetchGlimpseData() {
if lastDocument == nil {
GLIMPSE_ALL_USERS_DATA.order(by: TIMESTAMP, descending: true).limit(to: 3)
.getDocuments { [self] (snapshot, error) in.... //this block of code works properly
else {
glimpseTableView.tableFooterView = createSpinnerFooter()
GLIMPSE_ALL_USERS_DATA.order(by: TIMESTAMP, descending: true).start(afterDocument: lastDocument!).limit(to: 3)
.getDocuments { [self] (snapshot, error ) in.......//this block of code works properly
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
let position = scrollView.contentOffset.y
let maxOffset = scrollView.contentSize.height - scrollView.frame.size.height
if maxOffset - position <= 50 {
fetchGlimpseData()
}}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return glimpse.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let gCell = glimpseTableView.dequeueReusableCell(withIdentifier: "GlimpseCell", for: indexPath) as! GlimpseCell
gCell.delegateProfilePic = self
gCell.delegateGlimpseZoom = self
gCell.delegateGlimpseOption = self
gCell.configureGlimpseCell(glimpse: glimpse[indexPath.row])
gCell.separatorInset = .init(top: 5, left: 0, bottom: 5, right: 0)
gCell.backgroundColor = .beige
gCell.layer.borderWidth = 1
gCell.layer.borderColor = UIColor.gray.cgColor
gCell.selectionStyle = .none
return gCell
}
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
return .delete
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return false
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
guard editingStyle == .delete else { return }
glimpseTableView.beginUpdates()
glimpse.remove(at: indexPath.row)
glimpseTableView.deleteRows(at: [indexPath], with: .automatic)
glimpseTableView.reloadData()
glimpseTableView.endUpdates()
}
Post not yet marked as solved
I have a UITableView with 1 cell and when the array loads I just want for the user to see the content of the first 5 rows and blur the rest. So, if there is an array with 20 items, the first 5 need to be visible and the remaining 15 with a blur. With the code below, I'm able to just add a blur to row 5 only, I can't figure this out. Any help is greatly appreciated.
let visualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .light))
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]
if indexPath.row == 5 {
visualEffectView.frame = cell.bounds
visualEffectView.layer.masksToBounds = true
cell.addSubview(visualEffectView)
}
return cell
}
Post not yet marked as solved
Hi, I have a view controller with a searchBar and 2 tableViews. I run a query to Firebase and the results are shown in the top tableView (chargesTableView). The bottom tableView has a listener that when I select a row from the top tableView the values are displayed at the bottom (this is working OK). The searchBar is to filter the results in the top tableView (chargesTableView), the problem I'm having is with the search logic, no matter what I do when I type 1, 2 or 3 letters of the item I'm looking for, I don't get the result I want, sometimes I get an item that contains the first letter or sometimes i don't get anything at all. I don't know what else to do/check/try to get this working as expected. I want to be able to type the first 2,3 letters and get the list of items in the array. Any help is greatly appreciated. Here is my code:
class ChargesVC: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate {
var chargesClassFromCell = [Charges]()
var filteredCharges = [Charges]()
var searchBar = UISearchBar()
var inSearchMode: Bool = false
override func viewDidLoad() {
super.viewDidLoad()
searchBar.delegate = self
}
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
searchBar.showsCancelButton = true
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchBar.endEditing(true)
searchBar.showsCancelButton = false
searchBar.text = nil
inSearchMode = false
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
let searchText = searchBar.text!.lowercased()
if searchText.isEmpty || searchText == " " {
inSearchMode = false
chargesTableView.reloadData()
} else {
inSearchMode = true
filteredCharges = chargesClassFromCell.filter({ (searchResult) -> Bool in
return searchResult.chargeDescription.contains(searchText)
})
chargesTableView.reloadData()
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == chargesTableView {
if inSearchMode {
return filteredCharges.count
} else {
return chargesClassFromCell.count
}
} else { if tableView == patChargesTableView {
}
}
return patChargesClassFromCell.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView == chargesTableView {
let cell = tableView.dequeueReusableCell(withIdentifier: "ChargesCell", for: indexPath) as? ChargesCell
var charges: Charges!
if inSearchMode {
charges = filteredCharges[indexPath.row]
} else {
cell!.configureChargesListCell(charges: chargesClassFromCell[indexPath.row])
}
cell!.charges = charges
return cell!
} else if tableView == patChargesTableView {
let cell = tableView.dequeueReusableCell(withIdentifier: "PatChargesCell", for: indexPath) as? PatChargesCell
cell!.configurePatChargesListCell(patCharges: patChargesClassFromCell[indexPath.row])
cell!.patChargesCount.text = "\(indexPath.row + 1)" + " - "
return cell!
}
return UITableViewCell()
}
Hi, I have a cell with 2 buttons. Both buttons need to pass the same array but to 2 different view controllers depending on the user’s selection. The problem I’m having is that I cannot pass the array to one of the VCs, I get this error: “Expression type '()' is ambiguous without more context”. Any help is greatly appreciated. Here is my code:Inside the TableViewCellprotocol PatientDataCellDelegate {
func patCommentBtnTapped (ptData: PTData)
func dischargeBtnTapped (ptData: PTData)
}
@IBAction func addCommentBtnTapped(_ sender: UIButton) { //Button to segue to the Comments VC
delegate?.patCommentBtnTapped(ptData: ptData)
}
@IBAction func patientDischargeBtnTapped(_ sender: UIButton) { //Button to segue to the Discharge VC
delegate?.dischargeBtnTapped(ptData: ptData)
}View Controller override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToComments" {
if let commtsVC = segue.destination as? CommentsVC {
if let ptDatas = sender as? PTData {
commtsVC.ptDatas = ptDatas
}
}
} else if segue.identifier == "goToDischarge" {
if let discharVC = segue.destination as? DischargeVC {
if let ptDataFromCell = sender as? PTData {
discharVC.patDischargeFromCell = ptDataFromCell
}
}
}
}
}
extension PatdataVC: PatientDataCellDelegate {
func patCommentBtnTapped (ptData: PTData) { //Segue to Comments VC
performSegue(withIdentifier: "goToComments", sender: ptData)
}
func dischargeBtnTapped(ptData: PTData) {. // Segue to Discharge VC
performSegue(withIdentifier: "goToDischarge", sender: ptData)
}
}DischargeVCvar patDischargeFromCell = [DischargePatient]()
Post not yet marked as solved
I’m working on this app that runs 2 different queries to Firebase. The first Firebase query displays the data inside a pickerView, the second is a query to a “users” collection and pulls a custom field. Both queries are working as expected, pickerView displays the info and I’m able to print the results of the user’s collection to the console. The issue I’m having is that I’m trying to pass the value inside the custom field userSpecialtyCode to the next VC and is not working. I'm not sure what I'm missing. Any help is greatly appreciated. Here is my code:class PatfilterVC: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate {
@IBOutlet weak var hospNameTxt: UITextField!
@IBOutlet weak var getDataBtn: UIButton!
@IBOutlet weak var infoPickerViewer: UIPickerView!
private var textFieldSelected = UITextField()
private var pickerView: UIPickerView?
private var handle: AuthStateDidChangeListenerHandle?
private var userListener: ListenerRegistration!
private var hospitalClass = [HospitalList]()
private var hospCollectionRef: CollectionReference!
private var hospCode: HospitalList! = nil
private var loggedInUserClass = [UserSpecialty]()
private var usersCollectionRef: CollectionReference!
private var currentUserSpecialty: UserSpecialty! = nil
override func viewDidLoad() {
super.viewDidLoad()
overrideUserInterfaceStyle = .light
let pickerView = UIPickerView()
infoPickerViewer.delegate = self
infoPickerViewer.dataSource = self
hospNameTxt.inputView = pickerView
hospNameTxt.delegate = self
self.infoPickerViewer = pickerView
self.infoPickerViewer?.delegate = self
self.infoPickerViewer?.dataSource = self
self.infoPickerViewer?.reloadAllComponents()
hospCollectionRef = Firestore.firestore().collection(HOSPITAL_REF)
usersCollectionRef = Firestore.firestore().collection(USERS_REF)
handle = Auth.auth().addStateDidChangeListener({ (auth, user) in
if user == nil {
self.getDataBtn.isUserInteractionEnabled = false
self.infoPickerViewer.isUserInteractionEnabled = false
} else {
self.getDataBtn.isUserInteractionEnabled = true
self.infoPickerViewer.isUserInteractionEnabled = true
self.setListener()
}
})
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(UIInputViewController.dismissKeyboard))
view.addGestureRecognizer(tap)
getHospitalList()
getUserSpecialty()
}
@objc func dismissKeyboard() {
view.endEditing(true)
}
override func viewWillAppear(_ animated: Bool) {
handle = Auth.auth().addStateDidChangeListener({ (auth, user) in
if user == nil {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let LoginVC = storyboard.instantiateViewController(withIdentifier: "LoginVC")
self.present(LoginVC, animated: true, completion: nil)
} else {
self.setListener()
}
})
}
override func viewWillDisappear(_ animated: Bool) {
if userListener != nil {
userListener.remove()
}
}
func setListener() {
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func textFieldDidBeginEditing(_ textField: UITextField) {
textFieldSelected = textField
}
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
self.pickerView?.reloadAllComponents()
return true
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return hospitalClass.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return hospitalClass[row].hospitalName
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
hospCode = hospitalClass[row]
let hosp = hospitalClass[row].hospitalName
hospNameTxt.text = hosp
}
@IBAction func getDataTapped(_ sender: Any) {
guard hospCode != nil else {return} //I'm able to pass this to ResultsdataVC
guard currentUserSpecialty != nil else {return} //I'm not able to pass, value returns nil
performSegue(withIdentifier: "goToResults", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToResults" {
let vc = segue.destination as! ResultsdataVC
if let hosp = hospCode {
vc.hospCodeFromVC = hosp.hospitalCode
}
if let user = currentUserSpecialty {
vc.userSpecFromVC = user.userSpecialtyCode
}
}
}
//this query displays in the pickerView
func getHospitalList() {
let hospListQuery = hospCollectionRef?
.order(by: HOSPITAL_NAME, descending: false)
hospListQuery?.getDocuments { (snapshot, error) in
if let err = error {
debugPrint("error fetching docs: \(err)")
} else {
self.infoPickerViewer.reloadAllComponents()
let snap = snapshot
for document in snap!.documents {
let data = document.data()
let hospitalCode = data[HOSPITAL_CODE] as? String ?? ""
let hospitalName = data[HOSPITAL_NAME] as? String ?? ""
let hospList = HospitalList(hospitalCode: hospitalCode, hospitalName: hospitalName)
self.hospitalClass.append(hospList)
}
}
}
}
//this query gets the values from Firebase but i cannot pass userSpecialtyCode
// to the next viewController
func getUserSpecialty() {
if let loggedInUser = Auth.auth().currentUser?.uid {
let docRef = usersCollectionRef.document(loggedInUser)
docRef.getDocument { ( document, error) in
if let document = document, document.exists {
let data = document.data()
let userSpecialtyCode = data?[SPECIALTY_CODE] as? String ?? ""
let loggedInUserId = data?[LOGGED_IN_USER_ID] as? String ?? ""
let loggedUser = UserSpecialty(userSpecialtyCode: userSpecialtyCode, loggedInUserId: loggedInUserId)
self.loggedInUserClass.append(loggedUser)
print("specCode", userSpecialtyCode as Any) //IT PRINTS THE CORRECT VALUE
print("loggedInUser", loggedInUserId as Any) //IT PRINTS THE USER ID
} else {
print("no document")
}
}
}
}
@IBAction func logoutTapped(_ sender: Any) {
let firebaseAuth = Auth.auth()
do {
try firebaseAuth.signOut()
} catch let signoutError as NSError {
debugPrint("Error signing out: \(signoutError)")
}
}
}
Hi , I've been working on thsi small project (https://forums.developer.apple.com/message/409478#409478 ) but now i'm stuck with the following. The pickerView is populating the info from Firebase with no issues. Each Firebase collection has 2 strings: itemName and itemCode. The pickerView displays "itemName" only, now, i need to grab the value inside itemCode to send it to the next VC. Here is how i have the pickerView setup:func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if labelTxt.isFirstResponder {
return itemsClass[row].itemName
}
return nil
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if labelTxt.isFirstResponder {
let item = itemsClass[row].itemName
print("ITEMCODE2", itemsClass[row].itemCode as Any)
labelTxt.text = item
}
}
@IBAction func sendInfo(_ sender: Any) {
if ITEMS_CODE = { //here I do not know how to load the the second variable inside the ItemInfo.
}
performSegue(withIdentifier: "goToInfo", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToInfo" {
let vc = segue.destination as! infoVC
vc.fromPicker = ITEMS_CODE //This returns nil when i print to the console
}
}How do I get itemCode so that i can segue to the next VC? Thank you!
CODE HAS BEEN UPDATED AND IS WORKING AS EXPECTED.Hello, I have a View Controller with a text field and a pickerview. I want to display the data i have stored in Firebase inside the pickerview. I'm able to retrieve and print the data from Firebase but I can't find a way to display it inside the picker view. Here is my code:import UIKit
import Firebase
class pickerVC: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate {
@IBOutlet weak var labelTxt: UITextField!
@IBOutlet weak var infoPickerViewer: UIPickerView!
var dbRef: CollectionReference!
var pickerView: UIPickerView?
var itemsClass = [ItemInfo]()
override func viewDidLoad() {
super.viewDidLoad()
let pickerView = UIPickerView()
infoPickerViewer.delegate = self
infoPickerViewer.dataSource = self
dbRef = Firestore.firestore().collection(ITEMS_REF)
labelTxt.inputView = pickerView
labelTxt.delegate = self
self.infoPickerViewer = pickerView
self.infoPickerViewer?.delegate = self
self.infoPickerViewer?.dataSource = self
self.infoPickerViewer.reloadAllComponents()
getItems()
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func textFieldDidBeginEditing(_ textField: UITextField) {
labelTxt = textField
}
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
self.pickerView?.reloadAllComponents()
return true
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if labelTxt.isFirstResponder {
return self.itemsClass.count
}
return 0
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if labelTxt.isFirstResponder {
return itemsClass[row].itemName
}
return nil
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if labelTxt.isFirstResponder {
let item = itemsClass[row].itemName
labelTxt.text = item
}
}
func getItems() {
dbRef.getDocuments { (snapshot, error) in
if let err = error {
debugPrint("error fetching docs: \(err)")
} else {
self.infoPickerViewer.reloadAllComponents()
let snap = snapshot
for document in snap!.documents {
let data = document.data()
let itemCode = data[ITEMS_CODE] as? String ?? ""
let itemName = data[ITEMS_NAME] as? String ?? ""
let t = ItemInfo(itemCode: itemCode, itemName: itemName)
self.itemsClass.append(t)
print("ITEMS_CODE", itemCode as Any)
print("ITEMS_NAME", itemName as Any)
}
}
}
}
}The Firebase DB is structured as follow:collection/AutoID/itemCode: "item1" itemName: "item2"collection/AutoID/itemCode: "item3" itemName: "item4"I only need to display the itemName inside the pickerview, the itemCode I'm going to use it to run a query.Any help with this is greatly appreciated.
ello, i'm running a query to Firebase and i need to get the document ID of the collection. This is the code to run the query:Variableprivate var ptListInCell = [PTList]()@IBAction func getDataTapped(_ sender: Any) {
SVProgressHUD.show()
if HOSP != (hospnameTxt.text!) {
ptListQuery = ptListCollectionRef?.whereField("hosp", isEqualTo: (hospnameTxt.text!))
}
ptListQuery?.getDocuments { (snapshot, error) in
if let err = error {
debugPrint("error getting data: \(err)")
} else {
guard let snap = snapshot else { return }
for document in snap.documents {
let data = document.data()
let ptName = data[PTNAME] as? String ?? ""
let assignedMd = data[ASSIGNEDMD] as? String ?? ""
let officeMd = data[OFFICEMD] as? String ?? ""
let assignedDate = data[ASSIGNEDDATE] as? String ?? ""
let seeNoSee = data[SEENOSEE] as? String ?? ""
let room = data[ROOM] as? String ?? ""
let app = data[APP] as? String ?? ""
let documentId = document.documentID
print("documentId", documentId)
let newPtList = PTList(ptName: ptName, assignedMd: assignedMd, officeMd: officeMd, assignedDate: assignedDate, seeNoSee: seeNoSee, room: room, app: app, documentId: documentId)
print("newPtList", newPtList)
print("documentId", documentId)
self.ptListInCell.append(newPtList)
}
}it pulls everything but the documentID. When i print to the console:print(ptlist?.documentId asAny)Result is nil. thank you!
i'm running a query to Firebase and the results are displaying in a custom cell. The cell has a UIButton that when tapped it goes to another view controller where the user can enter info. The question i have is, how do i send the array in the custom cell to the next view controller? i need to send the array so i can reference the subcollection of info i'm going to add for each array. Segue is working properly, when i print to the console, the array is empty "nil". Any help is greatly appreciated.Custom Cellimport UIKit
import Firebase
protocol PatCellCommentsDelegate {
func patCommentBtnTapped (ptCommentsInCell: [Comment])
}
class PatdataCell: UITableViewCell {
@IBOutlet weak var ptnameLbl: UILabel!
@IBOutlet weak var dobLbl: UILabel!
@IBOutlet weak var finLbl: UILabel!
@IBOutlet weak var officemdLbl: UILabel!
@IBOutlet weak var assignedmdLbl: UILabel?
@IBOutlet weak var appnameLbl: UILabel!
@IBOutlet weak var assigneddateLbl: UILabel!
@IBOutlet weak var roomnumberLbl: UILabel?
@IBOutlet weak var diagnosesLbl: UILabel!
@IBOutlet weak var reasonforadmitorconsultLbl: UILabel!
@IBOutlet weak var goalofhospitalizationLbl: UILabel!
@IBOutlet weak var seenoseeLbl: UILabel?
@IBOutlet weak var notestocboLbl: UILabel!
@IBOutlet weak var numCommentsLbl: UILabel!
@IBOutlet weak var hospitalLbl: UILabel!
@IBOutlet weak var teamLbl: UILabel!
@IBOutlet weak var addCommentBtn: UIButton!
var ptdata: PTData!
var ptCommentsInCell = [Comment]()
var delegate: PatCellCommentsDelegate?
override func awakeFromNib() {
super.awakeFromNib()
}
func configurePatDataCell(ptdata: PTData, delegate:
PatCellCommentsDelegate) {
self.ptdata = ptdata
self.delegate = delegate
ptnameLbl.text = ptdata.ptname
dobLbl.text = ptdata.dob
finLbl.text = ptdata.fin
officemdLbl.text = ptdata.officemd
assignedmdLbl?.text = ptdata.assignedmd
appnameLbl.text = ptdata.app
assigneddateLbl.text = ptdata.assigneddate
roomnumberLbl?.text = ptdata.room
diagnosesLbl.text = ptdata.diagnoses
reasonforadmitorconsultLbl.text = ptdata.reasonforadmitorconsult
goalofhospitalizationLbl.text = ptdata.goalofhospitalization
seenoseeLbl?.text = ptdata.seenosee
notestocboLbl.text = ptdata.notestocbo
numCommentsLbl.text = ptdata.comments
hospitalLbl.text = ptdata.hosp
teamLbl.text = ptdata.team
}
@IBAction func addCommentBtnTapped(_ sender: Any) {
//trying to send data to commentsVC from this cell
delegate?.patCommentBtnTapped(ptCommentsInCell: self.ptCommentsInCell)
}
}View Controllerimport UIKit
import Firebase
import SVProgressHUD
class PatdataVC: UIViewController, UITableViewDelegate, UITableViewDataSource, PatCellCommentsDelegate {
@IBOutlet weak var patDataTableView: UITableView!
var ptdatas = [PTData]()
var ptCommentsToPass = [Comment]()
override func viewDidLoad() {
super.viewDidLoad()
patDataTableView.delegate = self
patDataTableView.dataSource = self
patDataTableView.rowHeight = 1150
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToComments" {
let commtsVC = segue.destination as! CommentsVC
commtsVC.ptComments = ptCommentsToPass
SVProgressHUD.dismiss()
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return ptdatas.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView == patDataTableView {
let cell = tableView.dequeueReusableCell(withIdentifier: "PatdataCell", for: indexPath) as? PatdataCell
cell!.configurePatDataCell(ptdata: ptdatas[indexPath.row], delegate: self)
return cell!
}
return UITableViewCell()
}
func patCommentBtnTapped (ptCommentsInCell: [Comment]) {
self.ptCommentsToPass = ptCommentsInCell
print("ptcomments", ptCommentsInCell)
performSegue(withIdentifier: "goToComments", sender: self)
}
}
Post not yet marked as solved
ISSUE HAS BEEN FIXED. SEE POST: https://forums.developer.apple.com/message/374921#374921hello everyone, i'm new at coding and if possible i need help with my app. i'm trying to perform a segue from a button inside a custom cell to another VC. The button inside the cell is querying data from Firebase and grabbing the results from a query and using them to do a bigger query, then it needs to send the data in another VC. Every label within the cell has a value, i dont understand why the SEGUE is not working as excpected. Any help is greatly appreciated. Thank you!**Cell Protocol**protocol MyCellDelegate: class {
func sendDataFromCell(_ sender: Any)
}**CustomCell: ptlistCell**import UIKit
import Firebase
import FirebaseFirestore
class ptlistCell: UITableViewCell {
@IBOutlet private weak var ptnameLbl: UILabel!
@IBOutlet private weak var assignedmdLbl: UILabel!
@IBOutlet private weak var officemdLbl: UILabel!
@IBOutlet private weak var roomnumberLbl: UILabel!
@IBOutlet private weak var seenoseeLbl: UILabel!
@IBOutlet private weak var assigneddateLbl: UILabel!
@IBOutlet weak var ptdataBtn: UIButton!
var ptdatainfoRef: CollectionReference!
var query: Query?
var patdata = [PTData]()
var delegate: MyCellDelegate?
override func awakeFromNib() {
super.awakeFromNib()
ptdatainfoRef = Firestore.firestore().collection(PTLIST_REF)
}
func configureCell(ptlist: PTList) {
ptnameLbl.text = ptlist.ptname
assignedmdLbl.text = ptlist.assignedmd
officemdLbl.text = ptlist.officemd
roomnumberLbl.text = ptlist.room
seenoseeLbl.text = ptlist.seenosee
assigneddateLbl.text = ptlist.assigneddate
}
@IBAction func ptdataTapped(_ sender: Any) {
let query = ptdatainfoRef.whereField("ptname", isEqualTo: (ptnameLbl.text!))
.whereField("assignedmd", isEqualTo: (assignedmdLbl.text!))
.whereField("officemd", isEqualTo: (officemdLbl.text!))
.whereField("room", isEqualTo: (roomnumberLbl.text!))
.whereField("seenosee", isEqualTo: (seenoseeLbl.text!))
.whereField("assigneddate", isEqualTo: (assigneddateLbl.text!))
query.getDocuments { (snapshot, error) in
if let err = error {
debugPrint("error getting data: \(err)")
} else {
guard let snap = snapshot else { return }
for document in snap.documents {
let data = document.data()
let ptname = data[PTNAME] as? String ?? ""
let dob = data[DOB] as? String ?? ""
let fin = data[FIN] as? String ?? ""
let officemd = data[OFFICEMD] as? String ?? ""
let assignedmd = data[ASSIGNEDMD] as? String ?? ""
let assigneddate = data[ASSIGNEDDATE] as? String ?? ""
let room = data[ROOM] as? String ?? ""
let diagnoses = data[DIAGNOSES] as? String ?? ""
let reasonforadmitorconsult = data[REASONFORADMITORCONSULT] as? String ?? ""
let goalofhospitalization = data[GOALOFHOSPITALIZATION] as? String ?? ""
let seenosee = data[SEENOSEE] as? String ?? ""
let notestocbo = data[NOTESTOCBO] as? String ?? ""
let comments = data[COMMENTS] as? String ?? ""
let hosp = data[HOSP] as? String ?? ""
let team = data[TEAM] as? String ?? ""
let newPtdata = PTData (ptname: ptname, dob: dob, fin: fin, officemd: officemd, assignedmd: assignedmd, assigneddate: assigneddate, room: room, diagnoses: diagnoses, reasonforadmitorconsult: reasonforadmitorconsult, goalofhospitalization: goalofhospitalization, seenosee: seenosee, notestocbo: notestocbo, comments: comments, hosp: hosp, team: team)
self.patdata.append(newPtdata)
print(document.data())
};print(self.delegate)
if(self.delegate != nil) {
self.delegate?.sendDataFromCell(sender)
}
}
}
}
}**firstVC w customCell (ptlistcell)**import UIKit
import Firebase
class resultsdataVC: UIViewController, UITableViewDataSource, UITableViewDelegate, MyCellDelegate {
@IBOutlet weak var tableView: UITableView!
var ptlist: PTList!
var ptlists = [PTList]()
var tableVc: patdataVC!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return ptlists.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "ptlistCell", for: indexPath) as? ptlistCell {
cell.configureCell(ptlist: ptlists[indexPath.row])
return cell
}
return UITableViewCell()
}
func sendDataFromCell(_ sender: Any) {
performSegue(withIdentifier: "gotoptdata", sender: (Any).self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "gotoptdata" {
tableVc = segue.destination as? patdataVC
tableVc.tableViewCellDelegate = self as? MyCellDelegate
}
}
}**secondVC w customCell (ptdataCell)**import UIKit
import Firebase
import FirebaseFirestore
class patdataVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
var ptdata: PTData!
var patdata = [PTData]()
var tableViewCellDelegate: MyCellDelegate?
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return patdata.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "ptlistCell"
guard let cell = tableView.dequeueReusableCell(withIdentifier: "ptdataCell", for: indexPath) as? ptlistCell else {
fatalError("The dequeued cell is not an instance of TableViewCell.")
}
cell.delegate = tableViewCellDelegate
return cell
}
}**CustomCell: ptdataCell**import UIKit
import Firebase
class ptdataCell: UITableViewCell {
@IBOutlet weak var ptnameLbl2: UILabel!
@IBOutlet weak var dobLbl2: UILabel!
@IBOutlet weak var finLbl2: UILabel!
@IBOutlet weak var officemdLbl2: UILabel!
@IBOutlet weak var assignedmdLbl2: UILabel!
@IBOutlet weak var assigneddateLbl2: UILabel!
@IBOutlet weak var roomLbl2: UILabel!
@IBOutlet weak var diagnosesLbl2: UILabel!
@IBOutlet weak var reasonforadmitorconsultLbl2: UILabel!
@IBOutlet weak var goalofhospitalizationLbl2: UILabel!
@IBOutlet weak var seenoseeLbl2: UILabel!
@IBOutlet weak var notestocboLbl2: UILabel!
@IBOutlet weak var commentsLbl2: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
func configureCell(patdata: PTData) {
ptnameLbl2.text = patdata.ptname
dobLbl2.text = patdata.dob
finLbl2.text = patdata.fin
officemdLbl2.text = patdata.officemd
assignedmdLbl2.text = patdata.assignedmd
assigneddateLbl2.text = patdata.assigneddate
roomLbl2.text = patdata.room
diagnosesLbl2.text = patdata.diagnoses
reasonforadmitorconsultLbl2.text = patdata.reasonforadmitorconsult
goalofhospitalizationLbl2.text = patdata.goalofhospitalization
seenoseeLbl2.text = patdata.seenosee
notestocboLbl2.text = patdata.notestocbo
commentsLbl2.text = patdata.comments
}
}