Search code examples
arraysswiftnstableviewnstablecellview

Remove data from array on NSTableView with NSButton with Swift


I have a NSTableView with data populated from an array.

I've created a button which when tapped should remove the items from that row in the array.

I'm struggling with how you remove the data from the array and delete the table column?

My array reference is:

var messagesRef: Firebase!
var messages = [Message]()

func setupFirebase() {

    messagesRef = Firebase(url: "https://url")


    messagesRef.queryLimitedToLast(10).observeEventType(FEventType.ChildAdded, withBlock: { (snapshot) in
        let text = snapshot.value["text"] as? String
        let sender = snapshot.value["sender"] as? String
        let imageUrl = snapshot.value["imageUrl"] as? String

        let message = Message(text: text, sender: sender, imageUrl: imageUrl)
        self.messages.append(message)
        self.tableView.reloadData()


    })
}

and my table delegate and datasource is:

func numberOfRowsInTableView(tableView: NSTableView) -> Int {
    return self.messages.count
}

func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row: Int) -> NSView? {
    let result = tableView.makeViewWithIdentifier("cell", owner: self) as? secondviewTableCell



    let mess = messages[row]

    result?.textField?.stringValue = mess.text()
    result?.sendertextView.stringValue = mess.sender()

    result?.removeButton.target = self
    result?.removeButton.action = #selector(secondVC.removeFromScreen)



    return result

}

func removeFromScreen(){


    }

I've managed to remove the row in the TableView but I'm still struggling with removing the data from the row in the array.

Here's my function to remove the row:

@IBAction func removetablerow(object: NSButton) {

    let row = tableView.rowForView( object as NSView )
    if ( row > -1 ) {
        let indexSet = NSIndexSet( index:row )
        tableView.removeRowsAtIndexes( indexSet, withAnimation: NSTableViewAnimationOptions.EffectFade )
        NSTimer.scheduledTimerWithTimeInterval( 0.5, target: self, selector: #selector(secondVC.rowDeleted(_:)), userInfo: row, repeats: false )


    }
}

Solution

  • It's very easy in macOS using a view based table view.

    • Create a standard IBAction and connect the button in Interface Builder.
    • In the action get the row with row(for view: and pass the sender as view parameter, e.g.

      @IBAction func removeFromScreen(_ sender : NSButton)
      {
          let row = self.tableView.row(for: sender)
          messages.remove(at:row)
          tableView.removeRows(at: IndexSet(integer:row), withAnimation:.effectFade)
          // do other things with the row 
      }
      

    No extra target, no extra action.

    Edit:

    The Swift 2 equivalent is:

        @IBAction func removeFromScreen(sender : NSButton)
        {
            let row = tableView.rowForView(object)
            messages.removeAtIndex(row)
            tableView.removeRowsAtIndexes( NSIndexSet( index:row ), withAnimation: NSTableViewAnimationOptions.EffectFade )
           // do other things with the row
        }