Two NSTextView inside the same NSScrollView

Hello,

I am currently trying to implement an NSScrollView containing 2 NSTextView using the Storyboard in Xcode. I found the NSScrollView and a NSTextView inside a NSScrollView in the element library (pictures below)

But I haven't found a way to add another NSTextView inside any of them, the NSTextView can't even be found in the element library.

Maybe there's something I am missing or don't know.

I would really appreciate some help since I haven't found any while searching on existing questions.

Thanks in advance,

Cyprien

Answered by Claude31 in 691110022

If that may help, this is what I did to sync the vertical scroll of 2 tableViews (would be very similar):

  • IBOutlets for the 2 BorderedScrollView
@IBOutlet weak var rowHeaderScrollView: NSScrollView!
@IBOutlet weak var dataScrollView: NSScrollView!
  • In     override func windowDidLoad() {

      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)
    

To calculate bounds:

    func calculeBounds() {
        let totalHeight = dataTableView.frame.height  
        let headerHeight = dataTableView.headerView!.frame.height
        contentUpperBound = -headerHeight            
        let totalScrollHeight = dataScrollView.frame.height  
        contentLowerBound = totalHeight - totalScrollHeight   
    }
  • And responding to notifications:
    @objc func boundsDidChangeNotification(_ notification: Notification) {
        
        if notification.object as? NSClipView == dataScrollView.contentView {
            let origin = (notification.object as! NSClipView).bounds.origin.y 
            rowHeaderScrollView.contentView.bounds.origin.y = origin 

        } else if notification.object as? NSClipView == rowHeaderScrollView.contentView {
            let origin = rowHeaderScrollView.contentView.bounds.origin.y
            if rowHeaderScrollView.contentView.bounds.origin.y > contentLowerBound || rowHeaderScrollView.contentView.bounds.origin.y < contentUpperBound { return }
            
            dataScrollView.contentView.bounds.origin.y = origin 
        }

    }

Hope that will help.

I probably miss what you are trying to do.

I could insert 2 TextViews in a ScrollView:

And here is the object in Library

I can type text inside and scroll both of them at will:

So, what you want is to sync the scrolls ?

You would have to do it in code, by adjusting the other view contentView bounds (or visibleRect) when you scrolled.

You may have to create your own notification as in this example (that's Xamarin, so may be not totally relevant):

h t t p s : / / social.msdn.microsoft.com/Forums/en-US/23035d90-987e-4201-b8be-11f424271699/how-to-detect-when-nstextview-scrolls-vertically?forum=xamarinios

This is a complete case, a bit tricky https://stackoverflow.com/questions/6596567/synchronize-two-nsscrollview

Accepted Answer

If that may help, this is what I did to sync the vertical scroll of 2 tableViews (would be very similar):

  • IBOutlets for the 2 BorderedScrollView
@IBOutlet weak var rowHeaderScrollView: NSScrollView!
@IBOutlet weak var dataScrollView: NSScrollView!
  • In     override func windowDidLoad() {

      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)
    

To calculate bounds:

    func calculeBounds() {
        let totalHeight = dataTableView.frame.height  
        let headerHeight = dataTableView.headerView!.frame.height
        contentUpperBound = -headerHeight            
        let totalScrollHeight = dataScrollView.frame.height  
        contentLowerBound = totalHeight - totalScrollHeight   
    }
  • And responding to notifications:
    @objc func boundsDidChangeNotification(_ notification: Notification) {
        
        if notification.object as? NSClipView == dataScrollView.contentView {
            let origin = (notification.object as! NSClipView).bounds.origin.y 
            rowHeaderScrollView.contentView.bounds.origin.y = origin 

        } else if notification.object as? NSClipView == rowHeaderScrollView.contentView {
            let origin = rowHeaderScrollView.contentView.bounds.origin.y
            if rowHeaderScrollView.contentView.bounds.origin.y > contentLowerBound || rowHeaderScrollView.contentView.bounds.origin.y < contentUpperBound { return }
            
            dataScrollView.contentView.bounds.origin.y = origin 
        }

    }

Hope that will help.

Two NSTextView inside the same NSScrollView
 
 
Q