Mac开发基础13-NSTextView(一)
NSTextView
是 macOS 应用开发中相当强大的多行文本输入控件。它不仅支持文本输入和显示,还支持富文本、文本编辑、布局管理等功能。
常见 API 和基础技巧
初始化 NSTextView
程序化创建
Objective-C
// 创建一个NSScrollView作为NSTextView的容器,因为NSTextView通常需要带滚动条的容器
NSScrollView *scrollView = [[NSScrollView alloc] initWithFrame:NSMakeRect(0, 0, 400, 300)];
// 创建一个NSTextView实例
NSTextView *textView = [[NSTextView alloc] initWithFrame:NSMakeRect(0, 0, 400, 300)];
// 设置NSTextView可以编辑和选择
[textView setEditable:YES];
[textView setSelectable:YES];
// 将NSTextView添加到NSScrollView
[scrollView setDocumentView:textView];
Swift
// 创建一个NSScrollView作为NSTextView的容器,因为NSTextView通常需要带滚动条的容器
let scrollView = NSScrollView(frame: NSMakeRect(0, 0, 400, 300))
// 创建一个NSTextView实例
let textView = NSTextView(frame: NSMakeRect(0, 0, 400, 300))
// 设置NSTextView可以编辑和选择
textView.isEditable = true
textView.isSelectable = true
// 将NSTextView添加到NSScrollView
scrollView.documentView = textView
设置和获取文本内容
设置文本
Objective-C
// 设置纯文本
[textView setString:@"Hello, NSTextView!"];
// 设置富文本
NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:@"Hello, NSTextView!" attributes:@{NSForegroundColorAttributeName: [NSColor blueColor]}];
[textView.textStorage setAttributedString:attributedText];
Swift
// 设置纯文本
textView.string = "Hello, NSTextView!"
// 设置富文本
let attributedText = NSAttributedString(string: "Hello, NSTextView!", attributes: [.foregroundColor: NSColor.blue])
textView.textStorage?.setAttributedString(attributedText)
获取文本
Objective-C
// 获取纯文本
NSString *plainText = [textView string];
// 获取富文本
NSAttributedString *attributedText = [textView attributedString];
Swift
// 获取纯文本
let plainText = textView.string
// 获取富文本
let attributedText = textView.attributedString()
文本属性和样式
设置文本属性
Objective-C
// 设置文本字体
[textView setFont:[NSFont fontWithName:@"Helvetica" size:14]];
// 设置文本颜色
[textView setTextColor:[NSColor blackColor]];
// 设置文本对齐方式
[textView setAlignment:NSTextAlignmentLeft];
Swift
// 设置文本字体
textView.font = NSFont(name: "Helvetica", size: 14)
// 设置文本颜色
textView.textColor = NSColor.black
// 设置文本对齐方式
textView.alignment = .left
编辑和选择
禁用编辑和选择
Objective-C
// 禁用编辑
[textView setEditable:NO];
// 禁用选择
[textView setSelectable:NO];
Swift
// 禁用编辑
textView.isEditable = false
// 禁用选择
textView.isSelectable = false
行间距和段落样式
设置行间距和段落样式
Objective-C
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setLineSpacing:5.0]; // 设置行间距
NSDictionary *attributes = @{NSParagraphStyleAttributeName: paragraphStyle};
NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:@"Hello, NSTextView!" attributes:attributes];
[textView.textStorage setAttributedString:attrString];
Swift
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 5.0 // 设置行间距
let attributes: [NSAttributedString.Key: Any] = [.paragraphStyle: paragraphStyle]
let attrString = NSAttributedString(string: "Hello, NSTextView!", attributes: attributes)
textView.textStorage?.setAttributedString(attrString)
插入和删除文本
插入文本
Objective-C
// 插入文本到末尾
[textView.textStorage appendAttributedString:[[NSAttributedString alloc] initWithString:@" More text"]];
Swift
// 插入文本到末尾
textView.textStorage?.append(NSAttributedString(string: " More text"))
删除文本
Objective-C
// 删除指定范围的文本
NSRange range = NSMakeRange(0, 5);
[textView.textStorage deleteCharactersInRange:range];
Swift
// 删除指定范围的文本
let range = NSRange(location: 0, length: 5)
textView.textStorage?.deleteCharacters(in: range)
粘贴板操作
自定义粘贴板操作
Objective-C
- (void)paste:(id)sender {
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
NSString *pasteString = [pasteboard stringForType:NSPasteboardTypeString];
if ([self isValidInput:pasteString]) {
[textView insertText:pasteString];
} else {
NSBeep();
}
}
- (BOOL)isValidInput:(NSString *)input {
// 自定义校验逻辑
return YES;
}
Swift
override func paste(_ sender: Any?) {
let pasteboard = NSPasteboard.general
if let pasteString = pasteboard.string(forType: .string) {
if isValidInput(pasteString) {
textView.insertText(pasteString, replacementRange: textView.selectedRange())
} else {
NSBeep()
}
}
}
func isValidInput(_ input: String) -> Bool {
// 自定义校验逻辑
return true
}
深入探讨 NSTextView
1. NSTextView 和 NSTextStorage
NSTextView
是一个视图,它使用 NSTextStorage
来管理其内容。NSTextStorage
是一个特殊的 NSMutableAttributedString
,它可以自动通知其内容的更改。
2. 用户交互与编辑行为
用户交互事件
可以通过 NSNotification
获得用户与文本视图互动的通知。
Objective-C
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidChange:) name:NSTextDidChangeNotification object:textView];
- (void)textDidChange:(NSNotification *)notification {
NSTextView *changedTextView = notification.object;
NSLog(@"Text changed: %@", changedTextView.string);
}
Swift
NotificationCenter.default.addObserver(self, selector: #selector(textDidChange(_:)), name: NSText.didChangeNotification, object: textView)
@objc func textDidChange(_ notification: Notification) {
if let changedTextView = notification.object as? NSTextView {
print("Text changed: \(changedTextView.string)")
}
}
委托方法
通过实现 NSTextViewDelegate
,可以对文本编辑行为进行精细控制。
Objective-C
@interface ViewController () <NSTextViewDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
textView.delegate = self;
}
- (void)textDidChange:(NSNotification *)notification {
NSLog(@"Text did change");
}
- (BOOL)textView:(NSTextView *)textView shouldChangeTextInRange:(NSRange)affectedCharRange replacementString:(nullable NSString *)replacementString {
// 可以在这里进行输入校验
NSLog(@"Replacement string: %@", replacementString);
return YES;
}
@end
Swift
class ViewController: NSViewController, NSTextViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
textView.delegate = self
}
func textDidChange(_ notification: Notification) {
print("Text did change")
}
func textView(_ textView: NSTextView, shouldChangeTextIn affectedCharRange: NSRange, replacementString: String?) -> Bool {
// 可以在这里进行输入校验
print("Replacement string: \(replacementString ?? "")")
return true
}
}
3. 自动文档保存
NSDocument 是 NSTextView
的一个重要配套组件,可以用于自动保存文档。
使用 NSDocument 进行自动保存
Objective-C
@implementation MyDocument
- (instancetype)init {
self = [super init];
if (self) {
_textView = [[NSTextView alloc] init];
}
return self;
}
- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError {
// 返回保存文档数据
return [[_textView string] dataUsingEncoding:NSUTF8StringEncoding];
}
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError {
// 读取和加载文档数据
NSString *content = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
[_textView setString:content];
return YES;
}
@end
Swift
class MyDocument: NSDocument {
var textView: NSTextView = NSTextView()
override init() {
super.init()
}
override func data(ofType typeName: String) throws -> Data {
// 返回保存文档数据
return textView.string.data(using: .utf8) ?? Data()
}
override func read(from data: Data, ofType typeName: String) throws {
// 读取和加载文档数据
if let content = String(data: data, encoding: .utf8) {
textView.string = content
}
}
}
4. 扩展功能:代码高亮与语法检查
通过自定义 NSTextView
,可以实现如代码高亮、语法检查等高级功能。
代码高亮
Objective-C
- (void)highlightSyntax {
NSString *text = [textView string];
NSMutableAttributedString *highlightedText = [[NSMutableAttributedString alloc] initWithString:text];
// 添加高亮逻辑,这里只是简单演示
NSDictionary *attributes = @{NSForegroundColorAttributeName: [NSColor redColor]};
[highlightedText setAttributes:attributes range:NSMakeRange(0, text.length)];
[textView.textStorage setAttributedString:highlightedText];
}
Swift
func highlightSyntax() {
let text = textView.string
let highlightedText = NSMutableAttributedString(string: text)
// 添加高亮逻辑,这里只是简单演示
let attributes: [NSAttributedString.Key: Any] = [.foregroundColor: NSColor.red]
highlightedText.addAttributes(attributes, range: NSRange(location: 0, length: text.count))
textView.textStorage?.setAttributedString(highlightedText)
}
5. 自动文本排版
NSTextView
结合 NSLayoutManager
和 NSTextContainer
,可以实现复杂的文本排版和布局管理。
自定义布局
Objective-C
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithContainerSize:NSMakeSize(400, CGFLOAT_MAX)];
[layoutManager addTextContainer:textContainer];
textView = [[NSTextView alloc] initWithFrame:NSMakeRect(0, 0, 400, 300) textContainer:textContainer];
[textView setHorizontallyResizable:NO];
Swift
let layoutManager = NSLayoutManager()
let textContainer = NSTextContainer(containerSize: CGSize(width: 400, height: .greatestFiniteMagnitude))
layoutManager.addTextContainer(textContainer)
textView = NSTextView(frame: NSMakeRect(0, 0, 400, 300), textContainer: textContainer)
textView.isHorizontallyResizable = false
将来的你会感谢今天如此努力的你!
版权声明:本文为博主原创文章,未经博主允许不得转载。