Manage text storage and perform custom layout of text-based content in your app's views using TextKit.

TextKit Documentation

Posts under TextKit tag

47 Posts
Sort by:
Post not yet marked as solved
0 Replies
506 Views
Hey, Maybe someone can explain me why NSLayoutManager is giving me "unstable" layout? It's like it decides to include line-height-multiple of 1.2 sometimes: We're doing some custom text rendering and if I change font size by a bit (or other property), then suddenly there is this extra text spacing. What we noticed so far is that there is something special about the first font that was set on NSTextStorage, in that case text has no extra spacing. Once you change it to slightly modified font else - the extra spacing is introduced. It's not NSParagraphStyle.lineHeightMultiple - if I set it to something non default then it acts as extra, but doesn't solve the "layout instability" issue. Any clue what's causing this? or how to make it to be stable?
Posted
by _Paulius_.
Last updated
.
Post not yet marked as solved
1 Replies
588 Views
Short version: Is it possible to do the expensive parts of setting UITextView attributedText on a background queue in advance of the UITextView main thread setup? Long version: Setting attributedText on UITextView is expensive, and UILabel is not an option for us. Is there a way to create a text container and layout manager ourselves in order to perform the expensive work on another queue in advance of setting up the UITextView? Ideally we wouldn’t need to have the layout manager draw a bitmap that we show instead of the UITextView altogether. We’re currently calling the layout manager’s ensureLayout(..) function on a background queue but not seeing an improvement in the main thread performance of setting the attributedText on the UITextView. Does ensureLayout(..) not compute and cache the layout work? Or is the layout work not the expensive part of setting attributed text?
Posted
by jasonwinn.
Last updated
.
Post not yet marked as solved
0 Replies
627 Views
In the WebVTT video subtitle format, subtitles can be horizontal, vertical growing left, or vertical growing right. The natural text direction of NSTextView is horizontal; with setLayoutOrientation(_:) I get vertical text growing left. How can I get vertical text growing right? The documentation says that with setLayoutOrientation(_:) the text view's bounds are rotated by 90° clockwise, but manually rotating them by -90° with boundsRotation = -90 just rotates everything, including the text which should have the same orientation as before, just expanding in the opposite direction.
Posted
by Nickkk.
Last updated
.
Post not yet marked as solved
1 Replies
991 Views
The demo app has a problem: if you vertically shrink the window using the bottom edge and move it to position y0, then drag the bottom edge again to another position y1, parts of the document after y0 will not be rendered due to the fact the viewport bounds are not recalculated when frame height changes. My fix to this problem is to remove the check that inspects whether the text container width changed and always set the value of the text container size used by the text layout manager whenever frame size changes: this does fix the problem mentioned above. However, I would like to know exactly when will the text layout manager recalculate the viewport bounds. This is not documented anywhere, nor in the video.
Posted Last updated
.
Post not yet marked as solved
0 Replies
442 Views
I am just playing with NSTextList by creating a sample iOS app. The following is my code. import UIKit class ViewController: UIViewController { lazy var textView: UITextView = { let textView = UITextView() textView.text = "" textView.contentInsetAdjustmentBehavior = .automatic textView.backgroundColor = .white textView.font = UIFont.systemFont(ofSize: 20.0) textView.textColor = .black textView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ textView.widthAnchor.constraint(equalToConstant: 600.0), textView.heightAnchor.constraint(equalToConstant: 600.0) ]) return textView }() lazy var button: UIButton = { let button = UIButton() button.setTitle("End list", for: .normal) button.setTitleColor(.white, for: .normal) button.setTitleColor(.lightGray, for: .highlighted) button.backgroundColor = .black button.layer.cornerRadius = 8.0 button.addTarget(self, action: #selector(fixTapped), for: .touchUpInside) button.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ button.widthAnchor.constraint(equalToConstant: 100.0), button.heightAnchor.constraint(equalToConstant: 42.0) ]) return button }() override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .systemBlue view.addSubview(textView) view.addSubview(button) let tapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard)) view.addGestureRecognizer(tapGesture) NSLayoutConstraint.activate([ textView.centerXAnchor.constraint(equalTo: view.centerXAnchor), textView.centerYAnchor.constraint(equalTo: view.centerYAnchor) ]) NSLayoutConstraint.activate([ button.centerXAnchor.constraint(equalTo: view.centerXAnchor), button.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -20.0) ]) let list = NSTextList(markerFormat: .diamond, options: 0) list.startingItemNumber = 1 let paragraphStyle = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle paragraphStyle.textLists = [list] let attributes = [NSAttributedString.Key.paragraphStyle: paragraphStyle, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 24.0)] let attributedStr = NSMutableAttributedString(string: "\n\n\n\n\n", attributes: attributes) textView.textStorage.setAttributedString(attributedStr) } @objc func fixTapped() { } @objc func dismissKeyboard() { view.endEditing(true) } } When the app launches itself, I get 5 lines of diamond guys as shown in the following screenshot. If I keep pressing the delete key with a connected keyboard, the list will be gone as shown below. But if I press the RETURN key several times, the diamond list will come back as shown below. So how can I end this June TextList madness? In code, I have the dismissKeyboard function if I can end this madness programmatically. Thanks, Señor Tomato Spaghetti Chief Janitor at Southeastern Tomato Spaghetti Trade Association
Posted
by Tomato.
Last updated
.
Post not yet marked as solved
0 Replies
852 Views
When using a UITextView and setting its textContainer's exclusionPaths to a path which lies at the and of a line, the words at the end of the line are split into characters even though setting lineBreakMode to .byWordWrapping. This also happens when moving the image to the end of the line in Apple's sample code from the WWDC session "What's new in TextKit and text views from WWDC22": https://developer.apple.com/documentation/uikit/textkit/enriching_your_text_in_text_views
Posted
by Alipacman.
Last updated
.
Post not yet marked as solved
2 Replies
895 Views
I have an app that uses UITextView for some text editing. I have some custom operations I can do on the text that I want to be able to undo, and I'm representing those operations in a way that plugs into NSUndoManager nicely. For example, if I have a button that appends an emoji to the text, it looks something like this: func addEmoji() { let inserting = NSAttributedString(string: "😀") self.textStorage.append(inserting) let len = inserting.length let range = NSRange(location: self.textStorage.length - len, length: len) self.undoManager?.registerUndo(withTarget: self, handler: { view in view.textStorage.deleteCharacters(in: range) } } My goal is something like this: Type some text Press the emoji button to add the emoji Trigger undo (via gesture or keyboard shortcut) and the emoji is removed Trigger undo again and the typing from step 1 is reversed If I just type and then trigger undo, the typing is reversed as you'd expect. And if I just add the emoji and trigger undo, the emoji is removed. But if I do the sequence above, step 3 works but step 4 doesn't. The emoji is removed but the typing isn't reversed. Notably, if step 3 only changes attributes of the text, like applying a strikethrough to a selection, then the full undo chain works. I can type, apply strikethrough, undo strikethrough, and undo typing. It's almost as if changing the text invalidates the undo manager's previous operations? How do I insert my own changes into UITextView's NSUndoManager without invalidating its chain of other operations?
Posted Last updated
.