NSViewBoundsDidChangeNotification (Swift)

My ultmate goal in this OSX app is to sync the vertical scroll of 2 NSTableViews.


I've browsed a lot of material, but could not find a comprehensive solution.

There is an advice to use notification of bounds changes from the scrollView of the NSTableView

https://stackoverflow.com/questions/51174503/synchronise-scrolling-nstableview-with-a-nsoutlineview-in-swift-live-scroll-no?noredirect=1&lq=1

which leads to this :

h ttp://borkware.com/quickies/one?topic=NSScrollView


So, I am trying to use NSViewBoundsDidChangeNotification, in the following code


dataTableScrollView.contentView.postsBoundsChangedNotifications = true
NotificationCenter.default.addObserver(self, selector: #selector(boundsDidChangeNotification), name: .NSViewBoundsDidChangeNotification, object: dataTableScrollView.contentView)

I get a compiler error:

Type 'NSNotification.Name?' has no member 'NSViewBoundsDidChangeNotification'


So, looking at doc, I found the NSNotification.Name property

https://developer.apple.com/documentation/foundation/nsnotification

boundsDidChangeNotification


Type Property

boundsDidChangeNotification

Posted whenever the NSView’s bounds rectangle changes to a new value independently of the frame rectangle, but only when the view’s postsBoundsChangedNotifications property is true.

Declaration

class let boundsDidChangeNotification: NSNotification.Name


Trying code with

dataTableScrollView.contentView.postsBoundsChangedNotifications = true

NotificationCenter.default.addObserver(self, selector: #selector(boundsDidChangeNotification), name: .boundsDidChangeNotification, object: dataTableScrollView.contentView)


yields to the same error

Type 'NSNotification.Name?' has no member 'boundsDidChangeNotification'


So, at this stage I have 2 questions:

- what is the correct notification name ?


- i am not sure this will allow me to finely sync the 2 tableViews vertical scroll. I would do this in the selector:

        if notification.object as? NSTableView == dataTableView {
            rowHeaderScrollView.contentView.bounds.origin.y = dataScrollView.contentView.bounds.origin.y
        } else if notification.object as? NSTableView == rowHeaderTableView {
             dataScrollView.contentView.bounds.origin.y = rowHeaderScrollView.contentView.bounds.origin.y
        }


Is there a better way ?

Answered by Claude31 in 351335022

Solved.


Just need to use NSView.boundsDidChangeNotification.


For those who may need, the following provides a decent sync (even tyhough some lagging in sync) between the 2 tableViews.


In viewDidLoad, add observers


        dataScrollView.contentView.postsBoundsChangedNotifications = true
        NotificationCenter.default.addObserver(self, selector: #selector(boundsDidChangeNotification), name: NSView.boundsDidChangeNotification, object: dataScrollView.contentView)

        rowHeaderScrollView.contentView.postsBoundsChangedNotifications = true
        NotificationCenter.default.addObserver(self, selector: #selector(boundsDidChangeNotification), name: NSView.boundsDidChangeNotification, object: rowHeaderScrollView.contentView)

with the callback:


    @objc func boundsDidChangeNotification(_ notification: Notification) {

        if notification.object as? NSClipView == dataScrollView.contentView {
            rowHeaderScrollView.contentView.bounds.origin.y = dataScrollView.contentView.bounds.origin.y
        } else if notification.object as? NSClipView == rowHeaderScrollView.contentView {
            dataScrollView.contentView.bounds.origin.y = rowHeaderScrollView.contentView.bounds.origin.y
        }

    }
Accepted Answer

Solved.


Just need to use NSView.boundsDidChangeNotification.


For those who may need, the following provides a decent sync (even tyhough some lagging in sync) between the 2 tableViews.


In viewDidLoad, add observers


        dataScrollView.contentView.postsBoundsChangedNotifications = true
        NotificationCenter.default.addObserver(self, selector: #selector(boundsDidChangeNotification), name: NSView.boundsDidChangeNotification, object: dataScrollView.contentView)

        rowHeaderScrollView.contentView.postsBoundsChangedNotifications = true
        NotificationCenter.default.addObserver(self, selector: #selector(boundsDidChangeNotification), name: NSView.boundsDidChangeNotification, object: rowHeaderScrollView.contentView)

with the callback:


    @objc func boundsDidChangeNotification(_ notification: Notification) {

        if notification.object as? NSClipView == dataScrollView.contentView {
            rowHeaderScrollView.contentView.bounds.origin.y = dataScrollView.contentView.bounds.origin.y
        } else if notification.object as? NSClipView == rowHeaderScrollView.contentView {
            dataScrollView.contentView.bounds.origin.y = rowHeaderScrollView.contentView.bounds.origin.y
        }

    }
NSViewBoundsDidChangeNotification (Swift)
 
 
Q