Как настроить NSTextView программно с явным NSLayoutManager, NSTextStorage, NSTextContainer?
Следуя документации Apple, я пытаюсь настроить простой NSTextView
через два метода конструктора.
Я размещаю приведенный ниже код внутри viewDidAppear
метод контроллера представления представления контента. textView является экземпляром NSTextView
, frameRect - это рамка представления содержимого.
Следующий код Swift работает (дает мне редактируемый textView с текстом, отображаемым на экране):
textView = NSTextView(frame: frameRect!)
self.view.addSubview(textView)
textView.textStorage?.appendAttributedString(NSAttributedString(string: "Hello"))
Следующее НЕ работает (текстовое представление не редактируется и текст не отображается на экране):
var textStorage = NSTextStorage()
var layoutManager = NSLayoutManager()
textStorage.addLayoutManager(layoutManager)
var textContainer = NSTextContainer(containerSize: frameRect!.size)
layoutManager.addTextContainer(textContainer)
textView = NSTextView(frame: frameRect!, textContainer: textContainer)
textView.editable = true
textView.selectable = true
self.view.addSubview(textView)
textView.textStorage?.appendAttributedString(NSAttributedString(string: "Hello more complex"))
Что я делаю не так во втором примере? Я пытаюсь следовать примеру, приведенному в "Руководстве по архитектуре текста Какао" от Apple, где обсуждается настройка NSTextView
явно создавая свою сеть вспомогательных объектов.
3 ответа
Вы должны сохранить ссылку на NSTextStorage
переменная, которую вы создаете. Я не совсем уверен в механике всего этого, но похоже, что текстовое представление содержит только слабую ссылку на свой объект хранения текста. Как только этот объект выходит из области видимости, он больше не доступен для просмотра текста. Я думаю, что это соответствует шаблону проектирования MVC, где представления (NSTextView
в этом случае) должны быть независимыми от своих моделей (NSTextStorage
объект).
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
@IBOutlet weak var window: NSWindow!
var textView: NSTextView!
var textStorage: NSTextStorage! // STORE A REFERENCE
func applicationDidFinishLaunching(aNotification: NSNotification) {
var view = window.contentView as NSView
textStorage = NSTextStorage()
var layoutManager = NSLayoutManager()
textStorage.addLayoutManager(layoutManager)
var textContainer = NSTextContainer(containerSize: view.bounds.size)
layoutManager.addTextContainer(textContainer)
textView = NSTextView(frame: view.bounds, textContainer: textContainer)
textView.editable = true
textView.selectable = true
view.addSubview(textView)
textView.textStorage?.appendAttributedString(NSAttributedString(string: "Hello more complex"))
}
}
Протестировано в Xcode 12.4. на детских площадках:
import Cocoa
import AppKit
let textViewFrame = CGRect(x: 0, y: 0, width: 250, height: 90)
let textStorage = NSTextStorage()
var layoutManager = NSLayoutManager()
textStorage.addLayoutManager(layoutManager)
var textContainer = NSTextContainer(containerSize: textViewFrame.size)
layoutManager.addTextContainer(textContainer)
let textView = NSTextView(frame: textViewFrame, textContainer: textContainer)
textView.isEditable = true
textView.isSelectable = true
textView.textColor = NSColor.red
textView.string = "Why is this so complicated..."
#import <Cocoa/Cocoa.h>
@interface TextViewController : NSObject {
NSLayoutManager *secondLayout;
IBOutlet NSSplitView *columnView;
IBOutlet NSTextView *bottomView;
}
- (IBAction) addColumn: (id)sender;
@end
#import "TextViewController.h"
@implementation TextViewController
- (void)awakeFromNib
{
NSTextStorage *storage = [bottomView textStorage];
secondLayout = [NSLayoutManager new];
[storage addLayoutManager: secondLayout];
[secondLayout release];
[self addColumn: nil];
[self addColumn: nil];
}
- (IBAction) addColumn: (id)sender
{
NSRect frame = [columnView frame];
NSTextContainer *container = [[NSTextContainer alloc]
initWithContainerSize: frame.size];
[container setHeightTracksTextView: YES];
[container setWidthTracksTextView: YES];
[secondLayout addTextContainer: container];
[container release];
NSTextView *newView = [[NSTextView alloc] initWithFrame: frame
textContainer: container];
[columnView addSubview: newView];
[newView release];
}
@end