0

I'm a newbie in Swift -please have mercy- with my code, I can not remove .childRemoved from external Firebase server due to expected Int instead of Stringand can not figure out how to remove from my tableview a message that I'm erasing from the external Firebase

import UIKit
import Firebase

class FCViewController: UIViewController, UINavigationControllerDelegate {

var ref: FIRDatabaseReference!
    var messages: [FIRDataSnapshot]! = []

func configureDatabase() {

ref = FIRDatabase.database().reference()

ref.child("messages").observe(.childRemoved, with: { (snapshot) in

            // MY PROBLEM 1: can not remove this chat with such identifier from the external Firebase server because an Int is expected instead of an String
            self.messages.remove(at: snapshot.key)

            // MY PROBLEM 2: when solving PROBLEM 1, table does not reload from Firebase like this, check on the comments the link for the answer to this:
            // reload table to featch data from Firebase
            self.messagesTable.reloadData()



        }, withCancel: nil)

}

}

snapshot.key

prints: -KflJWAyY3KSyyN8RA5U

self.messages prints:

                [Snap (-KflJVkAYLaoEiFPD86N) {
                     name = "user 1";
                     text = fadsfd;
                     timestamp = "2017-03-21 14:42:45 +0000";
                     }, 
                 Snap (-KflJWAyY3KSyyN8RA5U) {
                      name = "user 1";
                      text = adsfasdf;
                      timestamp = "2017-03-21 14:42:45 +0000";
                     }]

Thank you!

Victor
  • 504
  • 3
  • 9
  • There are a number of issues you're going to run into but most importantly, you are storing a snapshot object into an array, and that's objects ID (not *key* but the *object id* will be a different id than what's returned in the .remove event. You shouldn't have to work around the Int issue - work with it. See my answer, and also see my answer to the question referenced in your answer. – Jay Mar 21 '17 at 17:11
  • Question for PROBLEM 2 can be found here: http://stackoverflow.com/questions/42983966/tableview-not-reloading-after-childremoved-from-external-firebase-server Thanks! @Jay – Victor Mar 23 '17 at 18:19
  • @Jay can you please share how addRemoveObserver() works? I don´t know how that can be called to get the removed index from the Array. Thanks – Victor Mar 24 '17 at 09:38
  • Are you referring to *.observe(.childRemoved* like I used in my answer? If so, it passes the node that was removed to your code. From there you get the key of the node and use that to remove the node from the array. My answer has that code to accomplish that task. – Jay Mar 24 '17 at 17:42
  • @Jay, that is correct. I'm having a hard time trying to do it with your proposal. Almost 20hours trying to figure this out... When you have same time, can you please have a look at it in this other question? Thank you very much. http://stackoverflow.com/questions/42983966/tableview-not-reloading-after-childremoved-from-external-firebase-server – Victor Mar 27 '17 at 16:01

2 Answers2

1

var messages: [FIRDataSnapshot]! = []

is an array of snapshots and you are trying to remove it via a string (snapshot.key is a string)

self.messages.remove(at: snapshot.key)

and Swift is expecting at: to be an integer index within the array.

I would suggest not doing this as the objects you stored in the array will be different (object id's) than the object that's referenced when it's removed.

You will be much better off working with an array of dictionaries or even for example, MessageClass objects, that have been populated with the data from a Firebase Snapshot with the key as one of it's parameters.

Here's some code covering all the bases

class MessageClass {
    var key = ""
    var name = ""
}

var messagesArray = [MessageClass]()

func readInAllMessages() {
    let messagesRef = ref.child("messages")
    messagesRef.observeSingleEvent(of: .value, with: { snapshot in
        for child in snapshot.children {
            let snap = child as! FIRDataSnapshot
            let msg = self.snapToMsgClass(child: snap)
            self.messagesArray.append(msg)
        }
    })
}

func addRemoveObserver() {
    let messagesRef = ref.child("messages")
    messagesRef.observe(.childRemoved, with: { snapshot in
        let keyToRemove = snapshot.key 

        if let i = self.messagesArray.index(where: { $0.key == keyToRemove }) {
            self.messagesArray.remove(at: i)
        }
    })
}

func snapToMsgClass(child: FIRDataSnapshot) -> MessageClass {
    let dict = child.value as! [String:Any]
    let name = dict["name"] as! String
    let msg = MessageClass()
    msg.name = name
    msg.key = child.key
    return msg
}
Jay
  • 34,438
  • 18
  • 52
  • 81
  • Thank you Jay, for sure a much more elegant, efficient and faster way... I'm having trouble with loading the table view putting this class in another file. This is my code: http://swift.sandbox.bluemix.net/#/repl/58d2ef29e32643285237252a What is it that I'm doing wrong to refresh the table? Thanks! – Victor Mar 22 '17 at 21:41
  • Dear @Jay , how do you get the removed item from the array when calling from a separate file in my example in the VC? Thanks – Victor Mar 23 '17 at 14:15
  • @Victor Can you post another question? I think others can benefit from it and any solutions we suggest. Also, if this answer helped, please accept it! – Jay Mar 23 '17 at 16:50
  • Dear @Jay: thank you very much. As you can imagine I´m also new here... :p I thought it was going to be better for other to see the whole answer here. I will do so now and let you know on the comments. :) Than you very much for your time and coding wisdom. – Victor Mar 23 '17 at 17:41
  • Question for PROBLEM 2 can be found here: http://stackoverflow.com/questions/42983966/tableview-not-reloading-after-childremoved-from-external-firebase-server Thanks! – Victor Mar 23 '17 at 18:20
  • @Victor This is the correct answer for the *question that was asked* - it's a working, tested and functional answer. – Jay Mar 27 '17 at 17:37
0

I found an answer that perfectly matches what I was looking by @mitchellmaler

It can be found here: https://stackoverflow.com/a/42102616/2780268

He basically does all the magic with indexOfSnapshotInArray and converting to index's.

If you can't beat the enemy, join them.

In this case with index's... that work around for the Int issue.

Thank you.

Community
  • 1
  • 1
Victor
  • 504
  • 3
  • 9
  • note that in that answer, it's brute-force iterating over every object in the array looking for the key. There are much more elegant, efficient and faster ways of doing that. – Jay Mar 21 '17 at 17:14
  • Dear @Jay a much more elegant, efficient and faster way is more than welcome as a better answer. ;) Please share the love. Thanks! – Victor Mar 22 '17 at 17:53
  • See my answer that covers the entire process. – Jay Mar 22 '17 at 18:07