Q:

Swift/Firebase change value from tableview

Basically I am experiencing some difficulties trying to change the value from Firebase in a tableview. I am currently trying to make a Facebook-post-like feature, allowing people to like your post. However, I am not quite sure how I would proceed with this. I want to give the user the ability to like each post, and then save the previous likes + the like that was given, and update it in firebase. As of right now, I only have the code to display each post, and also the @IBAction from the button(Like button). 
I am not sure how I would manage to access each specific post through only the table view, using indexPath.row(?). Here is the code I have so far:
Post edit:
So basically I have a tableview, containing a table view cell that displays the amount of likes each post has. To do this, I have this code in my viewDidLoad(), to just fetch the data from Firebase:
ref.childByAppendingPath("posts").queryOrderedByChild("timeRegistered").observeEventType(FEventType.ChildAdded) { (snapshot:FDataSnapshot!) in

        var dict = [String:String]()
        dict["keys"] = snapshot.key as? String
        dict["votes"] = snapshot.value["likes"] as? String
        self.posts.append(dict)

        self.tableView.reloadData()

    }

Just to mention, this code works, by using this code in the cellForRowAtIndexPath: cell.textLabel!.text = String(posts[indexPath.row]["names"]!)
However, I thought that the code that I used in viewDidLoad (.ChildAdded function) would work with ChildChanged as well, so this is what I came up with:
ref.childByAppendingPath("posts").queryOrderedByChild("timeRegistered").observeEventType(FEventType.ChildChanged) { (snapshot:FDataSnapshot!) in

        var dict = [String:String]()
        dict["keys"] = snapshot.key as? String
        dict["votes"] = snapshot.value["votes"] as? String
        self.posts.append(dict)

        self.tableView.reloadData()

    }

Unfortunately, it looks like the tableview just displays the new value (the value changed from an IBAction, I'll provide this code as well.) - while the old value just stays there. This is the code for changing value:
var key = posts[1]["keys"]
    ref.childByAppendingPath("posts").childByAppendingPath(key!).updateChildValues(["name":"Test name"])
    tableView.reloadData()

Still trying to figure out a better way of changing the exact value, through index - but that is not the case now (therefore posts[1]["keys"]). Do you seem to understand what the problem is?
To sum up: I want to click a button inside a table view cell, and adding a like to the specific post, and updating the total count in real time.

A:

There are multiple answers so here's a few things:
The ChildChanged event is one issue. When a child is changed your code is appending it onto the array, creating a duplicate child with different data. What you should be doing is determining which child it is, get that dictionary from the array and update the values with the new values.
The followup comments asks 'how do you do that'.
There are a number of ways to get to it depending on how you want to store your data. I'll give two examples:
Suppose you have a Post structure (object) that contains information about each post. This is a way better solution than working with dictionaries. The structure will contain the firebase key, the msg and the uid of the user that made the post and you store those Posts in a postsArray
struct Post {
    var firebaseKey : String?
    var msg: String?
    var uid: String?

    init(aFirebaseKey: String, aMsg: String, aUid: String ) {
        self.firebaseKey = aFirebaseKey
        self.msg = aMsg
        self.uid = aUid
    }
}

var postsArray = [Post]()

and suppose you are observing the posts node for changes:
postsRef.observeEventType(.ChildChanged, withBlock: { snapshot in
  let changedKey = snapshot.key //the firebase key
  if let index = self.postsArray.indexOf({$0.firebaseKey == changedKey}) {
    print(index) //index is the index of the Post in the array
    let changedPost = self.postsArray[index]
    //update the values
    self.tableView.reloadData
}

and to make it complete, the initial loading of the posts
postsRef.observeSingleEventOfType(.Value, withBlock: { snapshot in
  for child in snapshot.children {

    let theKey = child.key as String
    let theMsg = child.value["msg"] as! String
    let theUid = child.value["user"] as! String

    let p = Post(aFirebaseKey: theKey, aMsg: theMsg, aUid: theUid)

    self.postsArray.append(p)              
  }
})

Another option is to keep side by side arrays.
keysArray[String]()
valuesArray[Dictionary]()

Using similar code, in the childChanged event get the firebase key and then simply find that key within the keysArray which will return it's index. Then use the returned index to get the values from the valuesArray; update them and reloadTableview.
let index= keysArray.indexOf(firebaseKey) //get the index for this post

let postToUpdate = self.valuesArray[index]
//update the Post

Of course when initially loading the arrays, you put the keys in the keysArray and the values in the valuesArray

