当前位置: 动力学知识库 > 问答 > 编程问答 >

ios - Firebase + Swift: Unable to delete rows in tableView

问题描述:

I am fairly new to the realm of coding and I am trying to implementing tableView with Firebase. What I am trying to achieve is to:

  1. Create a 'settings' page using tableView where users can input their favourite location
  2. Create a form (I use Eureka here) for users to pick certain options from the favourites they input in the settings page
  3. Allow deletion of those 'favourites'

In order for the forms to work, I pull the Firebase data at AppDelegate filtered by user.uid. to populate those 'favourites settings'. When I try to delete rows using commitEdittingStyle at the 'settings' , it throws the error of invalid number of rows. I tried googling various solution and also attempted dispatch_async but it somehow just doesn't quite solve my problem. Some snippets of my code as follows:

public var setUpFavLocations: [(String)] = []

public var favLocDatabase: [FIRDataSnapshot]! = []

@UIApplicationMain

class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?

var ref: FIRDatabaseReference!

var _refHandle: FIRDatabaseHandle!

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

FIRApp.configure()

let favLocVC: UITableViewController = FavLocationsTableViewController(style: UITableViewStyle.Plain)

ref = FIRDatabase.database().reference()

if let user = FIRAuth.auth()?.currentUser {

self.ref.child("settings").queryOrderedByChild("user").queryEqualToValue(user.uid).observeEventType(.ChildAdded, withBlock: { (snapshot) in

favLocDatabase.append(snapshot)

let insertionIndexPath = NSIndexPath(forRow: favLocDatabase.count - 1, inSection: 0)

favLocVC.tableView.insertRowsAtIndexPaths([insertionIndexPath], withRowAnimation: .Automatic)

})

self.ref.child("settings").queryOrderedByChild("user").queryEqualToValue(user.uid).observeEventType(.ChildAdded, withBlock: { (snapshot) in

setUpFavLocations.append(snapshot.value?["favLocation"] as! String)

})

//At FavLocationsTableViewController, aka at the settings page

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

print("count \(setUpFavLocations.count)")

return setUpFavLocations.count

}

override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {

if editingStyle == .Delete {

if let user = FIRAuth.auth()?.currentUser {

let row = favLocDatabase[indexPath.row]

self.ref.child("settings").queryOrderedByChild("user").queryEqualToValue(user.uid).observeEventType(.ChildRemoved, withBlock: { (snapshot) -> Void in

favLocDatabase.removeAtIndex(indexPath.row)

self.tableView.deleteRowsAtIndexPaths([NSIndexPath(forRow: indexPath.row, inSection: 0)], withRowAnimation: .Automatic)

})

row.ref.removeValue()

}

}

}

Doing this throws me the following error

Terminating app due to uncaught exception

'NSInternalInconsistencyException', reason: 'Invalid update: invalid

number of rows in section 0. The number of rows contained in an

existing section after the update (5) must be equal to the number of

rows contained in that section before the update (5), plus or minus

the number of rows inserted or deleted from that section (0 inserted,

1 deleted) and plus or minus the number of rows moved into or out of

that section (0 moved in, 0 moved out).'

Pls help, I'm pretty stuck here for days. Much appreciated.

网友答案:

You are creating a new listener every time you delete a row, that can't be good.

Try moving:

self.ref.child("settings").queryOrderedByChild("user").queryEqualToValue(user.uid).observeEventType(.ChildRemoved, withBlock: { (snapshot) -> Void in
    favLocDatabase.removeAtIndex(indexPath.row)
    self.tableView.deleteRowsAtIndexPaths([NSIndexPath(forRow: indexPath.row, inSection: 0)], withRowAnimation: .Automatic)
})

into your AppDelegate with the other listeners.

Also I noticed you are not handling your observers, so when you open and close your app, the observers will duplicate. You should remove the observers when the app enters the background and re-instantiate them when the app enters the foreground. You'll find methods for these events in your AppDelegate.

分享给朋友:
您可能感兴趣的文章:
随机阅读: