Reputation: 358
I have the following Swift & Firebase code which returns the data as expected (initially) but if the data is changed by another user and the current user goes back into the table, it shows the old data. It only updates with the new data if the user goes out and back into the table where it then shows the correct data.
It's as if the data is cached but I have persistence disabled):
import UIKit
import Firebase
class Agent_NewRequests: UITableViewController {
let custom = custom()
var dbConnector = FIRDatabase.database().reference()
var userID:String!
var searchResults = [agentNewRequests]()
var requestID:String!
var loadingOverlay = LoadingOverlay()
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(animated: Bool) {
self.searchResults.removeAll(keepCapacity: false)
FIRAuth.auth()!.addAuthStateDidChangeListener() { (auth, user) in
if user != nil {
// user authenticated
self.userID = user!.uid
self.retrieveRequests()
} else {
// No user is signed in
self.custom.showLogin(self.self)
}
}
}
override func viewWillDisappear(animated: Bool) {
dbConnector.removeAllObservers()
}
func retrieveRequests() {
if self.userID == "" {
loadingOverlay.hideOverlayView()
// todo - show error
return
}
loadingOverlay.showOverlay(self.view)
var timeLastUpdated = ""
self.searchResults.removeAll(keepCapacity: false)
let userRef = dbConnector.child("requests/\(self.userID)")
userRef.queryEqualToValue("Submitted", childKey: "status")
userRef.observeSingleEventOfType(.ChildAdded, withBlock: { snapshot in
guard snapshot.exists() else {
// No data found, handle error otherwise will crash
self.checkTable()
self.loadingOverlay.hideOverlayView()
return
}
if let _:String = snapshot.value!["status"] as? String { } else {
self.checkTable()
self.loadingOverlay.hideOverlayView()
return
}
let status = snapshot.value!["status"] as! String
if status != "Submitted" {
self.checkTable()
return
}
let key = snapshot.key as String
let tenantID = snapshot.value!["tenant_id"] as! String
let address = snapshot.value!["address"] as! String
let desc = snapshot.value!["description"] as! String
let timeUpdate:Int = snapshot.value!["time_updated"] as! Int
let priority = snapshot.value!["priority"] as! Int
let dateFormat = NSDateFormatter()
dateFormat.dateStyle = NSDateFormatterStyle.LongStyle
dateFormat.timeStyle = NSDateFormatterStyle.ShortStyle
if timeUpdate == 0 { // if it has never been updated, use time created instead for lastupdated
let cTimeInterval = snapshot.value!["time_created"] as? NSTimeInterval
let updateTime = NSDate(timeIntervalSince1970: cTimeInterval! / 1000)
timeLastUpdated = dateFormat.stringFromDate(updateTime)
} else {
let uTimeInterval = snapshot.value!["time_updated"] as? NSTimeInterval
let updateTime = NSDate(timeIntervalSince1970: uTimeInterval! / 1000)
timeLastUpdated = dateFormat.stringFromDate(updateTime)
}
var imgData:String = ""
self.searchResults += [agentNewRequests(requestID: key, tenantID: tenantID, address: address, description: desc, lastUpdated: timeLastUpdated, mediaData: mediaData, priority: priority)]
dispatch_async(dispatch_get_main_queue()){
self.checkTable()
}
}) { error in
print(error.description)
self.loadingOverlay.hideOverlayView()
}
}
func checkTable() {
if (self.searchResults.count > 0) {
self.searchResults = self.searchResults.reverse()
self.tableView.reloadData()
self.loadingOverlay.hideOverlayView()
// remove any previous signs of errorMessageLabel
self.tableView.backgroundView = nil
self.tableView.separatorColor = custom.UIColorFromRGB(0x574987, alphaValue: 1)
self.tableView.separatorStyle = UITableViewCellSeparatorStyle.SingleLine
} else {
self.tableView.reloadData()
self.loadingOverlay.hideOverlayView()
// Display a message that the table is empty
let errorMessageLabel = UILabel()
errorMessageLabel.frame = CGRectMake(0, 0, self.tableView.bounds.width, (self.tableView.bounds.height + 100))
errorMessageLabel.text = "No new requests found"
errorMessageLabel.numberOfLines = 1
errorMessageLabel.textColor = UIColor.blackColor()
errorMessageLabel.textAlignment = NSTextAlignment.Center
errorMessageLabel.sizeToFit()
self.tableView.backgroundView = errorMessageLabel
self.tableView.separatorColor = UIColor.clearColor()
self.tableView.separatorStyle = UITableViewCellSeparatorStyle.SingleLine
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:Agent_NewRequests_Cell = self.tableView.dequeueReusableCellWithIdentifier("requestCell")
as! Agent_NewRequests_Cell
cell.idLabel.text = searchResults[indexPath.row].description
cell.updatedLabel.text = searchResults[indexPath.row].lastUpdated
cell.addressLabel.text = searchResults[indexPath.row].address
return cell
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return searchResults.count
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
requestID = searchResults[indexPath.row].requestID
self.performSegueWithIdentifier("newToRequestCard", sender: indexPath);
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "newToRequestCard") {
let requestCard = segue.destinationViewController as! Agent_Request_Card;
requestCard.toPass_requestID = self.requestID
requestCard.toPass_agentID = self.userID
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
If I change it from .ObserveSingleEventOfType to .ObserveEventType it works as expected BUT... if the data is deleted elsewhere and there is no other data, the UI just sits listening for updates and I don't want that, I need the user to be told there is no data with a UI update (which never happens)
Upvotes: 3
Views: 745
Reputation: 1365
Use ObserveEventType
instead of ObserveSingleEventOfType
and just check whether or not the data is present. If it isn't, update the UI with a message. If it is, continue as normal.
Upvotes: 1