Displaying text in a NSScrollView (Swift)
Asked Answered
S

7

10

Just started to learn Swift and created a little macOS app in which I want to use a NSScrollView to display an attributed String. I’ve tried:

@IBOutlet var ScrollViewOutlet : NSScrollView
var attributedString = NSMutableAttributedString(string: myText)
ScrollViewOutlet.insertText(attributedString)

But that doesn’t seem to work. Feels confusing since doing the exact same with a NSTextView instead works like a charm.

What am I missing here?

Subedit answered 7/8, 2014 at 9:33 Comment(0)
S
6

It seems that the earlier beta versions (which featured Swift) of Xcode had some serious issues with this kind of outlets (as you can see here: http://swiftwtf.tumblr.com/post/88387419568/nstextview). However, since Xcode 6 Beta 6 it works.

textFieldOutlet.textStorage.mutableString.setString("Hello w0rld!")

To handle the String, creating an outlet for the textField instead of the scrollView itself is also a better practice.

Subedit answered 25/8, 2014 at 13:57 Comment(0)
N
15

In the following example, I added the scrollView in the interface builder as my starting point.

The following works if you your scrollView/textView is empty/blank OR if you need to append text in front of what is already in the scrollView/textView. If there is already text in the box, the new text is inserted in front of the existing text.

The documentView is an NSTextView

Swift 4.0

@IBOutlet weak var imageDestinationDirectory: NSScrollView!

...

let destinationText = "Text to display"
imageDestinationDirectory.documentView!.insertText(destinationText)
Nonalignment answered 18/11, 2017 at 11:49 Comment(0)
S
6

It seems that the earlier beta versions (which featured Swift) of Xcode had some serious issues with this kind of outlets (as you can see here: http://swiftwtf.tumblr.com/post/88387419568/nstextview). However, since Xcode 6 Beta 6 it works.

textFieldOutlet.textStorage.mutableString.setString("Hello w0rld!")

To handle the String, creating an outlet for the textField instead of the scrollView itself is also a better practice.

Subedit answered 25/8, 2014 at 13:57 Comment(0)
Z
5

Apple's has an article about setting up a text view inside a scroll view programmatically. Text System User Interface Layer Programming Guide: Putting an NSTextView Object in an NSScrollView You should read that for greatest understanding, but here's the code:

NSScrollView *scrollview = [[NSScrollView alloc] initWithFrame:[[theWindow contentView] frame]];
NSSize contentSize = [scrollview contentSize];

[scrollview setBorderType:NSNoBorder];
[scrollview setHasVerticalScroller:YES];
[scrollview setHasHorizontalScroller:NO];
[scrollview setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];

theTextView = [[NSTextView alloc] initWithFrame:NSMakeRect(0, 0, contentSize.width, contentSize.height)];
[theTextView setMinSize:NSMakeSize(0.0, contentSize.height)];
[theTextView setMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)];
[theTextView setVerticallyResizable:YES];
[theTextView setHorizontallyResizable:NO];
[theTextView setAutoresizingMask:NSViewWidthSizable];

[[theTextView textContainer] setContainerSize:NSMakeSize(contentSize.width, FLT_MAX)];
[[theTextView textContainer] setWidthTracksTextView:YES];
[scrollview setDocumentView:theTextView];
[theWindow setContentView:scrollview];
[theWindow makeKeyAndOrderFront:nil];
[theWindow makeFirstResponder:theTextView];

You can then set the text of the text view by operating on its textStorage object:

theTextView.textStorage.attributedString = attributedString;
Zapata answered 13/8, 2014 at 11:9 Comment(0)
B
3

Here's how to do it programmatically, with auto layout:

class ViewController: NSViewController {
    let scrollView = NSScrollView()
    let textView = NSTextView()

    override func viewDidLoad() {
        super.viewDidLoad()

        textView.maxSize = NSSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)
        textView.autoresizingMask = .width
        textView.isVerticallyResizable = true
        textView.textContainer?.widthTracksTextView = true

        view.addSubview(scrollView)
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        scrollView.documentView = textView

        NSLayoutConstraint.activate([
            scrollView.topAnchor.constraint(equalTo: view.topAnchor),
            scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
        ])
    }
}
Bekki answered 18/7, 2017 at 7:20 Comment(0)
W
3
@IBOutlet weak var scrollView: NSScrollView!

The documentView of the NSScrollView is an NSTextView, so in Swift you can use the following:

let textView : NSTextView? = scrollView?.documentView as? NSTextView
textView?.string = text
Wilonah answered 25/1, 2020 at 22:57 Comment(1)
I cannot get this to work in Swift 5.5.2. The textView is always nil. This is trying to cast an NSView to an NSTextField, which fails.Medalist
R
2

For NSScrollView:

@IBOutlet weak var textScroll: NSScrollView!

Check this out:

let text = textScroll.documentView!.textStorage!!
let attr = NSAttributedString(string: "Hello World")

text.appendAttributedString(attr)

This is very much in spirit of @mrtn.lxo solution, only done for NSScrollView and is using NSAttributedString.

Reeta answered 10/8, 2015 at 18:12 Comment(1)
The API must have changed because there is no textStorage in the documentView in Swift 5.5.2.Medalist
U
2

answer of ixany worked great, but as a beginner it looks me more time to figure it out, that outlet should be done for NSTextView and not for NSTextScroll. NSTextView is hidden inside of NSTextScroll. All Results Field is NSTextScroll in my case and Text View Results is NSTextView

Udine answered 7/10, 2016 at 1:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.