Matty265 Matty265 - 11 days ago 6
Swift Question

NSTableView Delegate methods won't get called

I'm currently trying to parse the reddit headlines from a specific subreddit and display these in an NSTableView. The thing is, the

numberOfRows
function gets called and returns the correct integer but the
tableView
delegate function never gets called.

As far as I can see everything is wired up correctly in the code.

ViewController:

@IBOutlet weak var tableView: NSTableView!

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
Downloader.load(url: URL(string: "https://www.reddit.com/r/" + "gaming" + ".json")!){
(result) in
let tvc = TableViewController(data: result)

self.tableView.delegate = tvc
self.tableView.dataSource = tvc
self.tableView.reloadData()
}
}


TableViewController:

class TableViewController: NSObject{

var json: JSON!

init(data: JSON) {
super.init()
self.json = data
}
}
extension TableViewController : NSTableViewDataSource {
func numberOfRows(in tableView: NSTableView) -> Int {
return JSONFormatController.getTitlesFrom(json: json).count
}
}
extension TableViewController : NSTableViewDelegate {
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
var titles = JSONFormatController.getTitlesFrom(json: json)
if let cell = tableView.make(withIdentifier: "entry", owner: nil) as? NSTableCellView {
cell.textField?.stringValue = titles[row]
return cell
} else {
return nil
}
}
}


The
result
variable and
getTitlesFrom
method do work, I checked these.

hnh hnh
Answer

I think your issue is that your TableViewController object is getting deallocated because you are not keeping a reference to it. Try this:

@IBOutlet weak var tableView: NSTableView!
var tvc : TableViewController!

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    Downloader.load(url: URL(string: "https://www.reddit.com/r/" + "gaming" + ".json")!){
        (result) in
        self.tvc = TableViewController(data: result)

        self.tableView.delegate   = self.tvc
        self.tableView.dataSource = self.tvc
        self.tableView.reloadData()
    }
}

Explanation: tvc is a local variable of the download block which is getting deallocated after it has executed. Presumably your assumption is that storing the tvc in delegate and/or dataSource is keeping tvc alive. But they are not, they are weak references.