NSTableView and big data

I need to display an NSTableView (through a NSWindowController) by interrogation a webService

for one of the interrogation, the webServices return me more than hundred rows of data

So there are 2 problems:

1. the datasource takes a big amount of memory

2. it can takes a long time before the datasource is entirely loaded


I think the solution is to interrogate the webservice for the number of visible lines (and further to asynchronously load some other lines to prepare the scrolling).


To obtain he number of visible lines, I do:

let nbVisibleRows = Int(myTable.frame.size.height / (myTable.rowHeight+1))

At the initialization of the window, I effectively obtains the good number of rows


My problem is that the window can be resized.

So I add and observer:

NotificationCenter.default.addObserver(self, selector: #selector(windowDidResize(_:)), name: NSWindow.didEndLiveResizeNotification, object: self)


and in the méthod windowDidResize I ask for the number of visible rows exactly as I wrote above.


I do do understand the size of the table.frame returned in the windowDidResize method


when I load the window, it returns for the table a height of 277.0, wich is correct

when I resize the window even from a very small amount, it returns for the table a height of 2886.0


So I can't calculate the number of visible rows


Any idea what I did wrong?

Accepted Reply

Exact, because the frame is for the scrollView, not the contentSize (visible tableview)

Replies

I would better try to call async, as you hinted.


Could you show the code or compare what you did with this


https://stackoverflow.com/questions/30625275/swift-tableview-displays-json-data-very-slow

all the call to webService is made async with alamoFire

I dont' know howto show the code, bea-cause it is ntegrated threw hundred of lines I write (everything is subclassed, to do work automatically)


I only wanted to know why the windowDidResize method give me an invalid height for the frame table


@objc func windowDidResize(_ notification: Notification) {
        Swift.print("windowResize: \(tableFactures.frame)")
        Swift.print("windowResize: \(notification.description)")
        let nbVisibleRangees = Int(tableFactures.frame.size.height / (tableFactures.rowHeight+1))
        Swift.print("nbVisibleRangees: \(nbVisibleRangees)")
    }

Have you set constraints on the tableView ?


If so, could be (just a guess), that it estimates the row height before performing exact computation.


Does the height change more when you resize more ? Or does it always stay in the 277 - 286 range ?


If so, I would suggest to use a lower estimate of cell height ; you may retrieve 1 or 2 extra data but that should not be a big deal.

Yes, I put constraints on the table. But when the window is resized, just a little bit, the height of the table becomes 2886 (not 286) and was 277 at the initiation of the window.Effectively, if it was just 1 or 2 extra data, it's not a big deal. But in this case, the difference is huge

Probably when you call the windowDidResize, some values are not yet set.


I cannot test just now, but you could try to do it in


override func viewWillLayoutSubviews() {


or better in


override func viewDidLayoutSubviews() {

The problem is that I work with NSWindowController, not vNSViewController


So, viewWillLayoutSubviews doesn't exists.


I've noticed something: for the forst display, if I calculate the number of visible rows and ask my webService to send this number of rows, when the cell to windowDidResize is done, the frame of the table is correct if the height of the window grows bigger.


but if the height of the windows become smaller, the frame of the table doesn't becomes smaller.

For NSViewController, you have


viewDidLayout()


Called immediately after the

layout()
method of the view controller's view is called.



Declaration

func viewDidLayout()

Discussion

You can override this method to perform tasks to follow the completion of layout of the view controller’s view. If you override this method, call this method on

super
at some point in your implementation in case a superclass also overrides this method.

The default implementation of this method does nothing.


Yes Claude, I understand, but I don't work with ViewController, but with windowController. And WindowController doesn't have a viewDidLayout method, and I don't find equivalent

OK sorry.


So, may be you could call it on window.contentView

I think about that, but I don't kown how to do it.

I noticed something: if you load 10 rows in a NSTableViewController, the frame has the height necessary to contains 10 rows.

If after that you load 100 rows in this NSTableView, the frame height change, to contains the 100 rows, even if the first 10 rows are visible. And this height will stay constant.


But I think I have the solution: in the windowDidLoad, I search for the NSScrollView containing the NSTableView. And in my windowDidResize method, I calculate the number of rows on the height of the NSScrollView, not on the height of the NSTableView. There is an error about 1 or 2 rows, but it works and I can reduce the amount of rows loaded

Exact, because the frame is for the scrollView, not the contentSize (visible tableview)