Mac开发基础14-NSTextView(二)
进阶使用和技巧
1. 扩展查找和替换功能
可以自定义查找和替换功能,包括高亮查找结果、批量替换等。
查找并高亮
Objective-C
- (void)highlightOccurrencesOfString:(NSString *)searchString {
// 清除之前的高亮效果
[textView.layoutManager removeTemporaryAttribute:NSBackgroundColorAttributeName forCharacterRange:NSMakeRange(0, textView.string.length)];
// 查找并高亮指定字符串
NSString *textViewString = textView.string;
NSRange searchRange = NSMakeRange(0, textViewString.length);
while (searchRange.location < textViewString.length) {
searchRange = [textViewString rangeOfString:searchString options:0 range:searchRange];
if (searchRange.location != NSNotFound) {
// 应用高亮颜色
[textView.layoutManager addTemporaryAttribute:NSBackgroundColorAttributeName value:[NSColor yellowColor] forCharacterRange:searchRange];
searchRange.location += searchRange.length;
searchRange.length = textViewString.length - searchRange.location;
} else {
break;
}
}
}
Swift
func highlightOccurrences(of searchString: String) {
// 清除之前的高亮效果
textView.layoutManager?.removeTemporaryAttribute(.backgroundColor, forCharacterRange: NSRange(location: 0, length: textView.string.utf16.count))
// 查找并高亮指定字符串
let textViewString = textView.string as NSString
var searchRange = NSRange(location: 0, length: textViewString.length)
while let foundRange = textViewString.range(of: searchString, options: [], range: searchRange).toRange() {
// 应用高亮颜色
textView.layoutManager?.addTemporaryAttribute(.backgroundColor, value: NSColor.yellow, forCharacterRange: NSRange(foundRange))
searchRange = NSRange(location: foundRange.upperBound, length: textViewString.length - foundRange.upperBound)
}
}
2. 自动链接检测
NSTextView
具有自动检测和格式化 URL 的功能,可以自动将 URL 链接转换为可点击的超链接。
启用自动链接检测
Objective-C
textView.automaticLinkDetectionEnabled = YES;
Swift
textView.isAutomaticLinkDetectionEnabled = true
3. 自定义上下文菜单
可以为 NSTextView
提供自定义的上下文菜单,以增加更多操作选项。
Objective-C
- (NSMenu *)menuForEvent:(NSEvent *)event {
NSMenu *menu = [[NSMenu alloc] initWithTitle:@"Context Menu"];
[menu addItemWithTitle:@"Custom Action" action:@selector(customAction:) keyEquivalent:@""];
[menu addItemWithTitle:@"Another Action" action:@selector(anotherAction:) keyEquivalent:@""];
return menu;
}
- (void)customAction:(id)sender {
NSLog(@"Custom action triggered");
}
- (void)anotherAction:(id)sender {
NSLog(@"Another action triggered");
}
Swift
override func menu(for event: NSEvent) -> NSMenu? {
let menu = NSMenu(title: "Context Menu")
menu.addItem(withTitle: "Custom Action", action: #selector(customAction(_:)), keyEquivalent: "")
menu.addItem(withTitle: "Another Action", action: #selector(anotherAction(_:)), keyEquivalent: "")
return menu
}
@objc func customAction(_ sender: Any?) {
print("Custom action triggered")
}
@objc func anotherAction(_ sender: Any?) {
print("Another action triggered")
}
4. 自定义文本标记(标注)
可以利用 NSTextView
的 NSLayoutManager
和 NSTextStorage
结合 NSAttachment
添加自定义的文本标记或标注。
Objective-C
- (void)addCustomMarkAtRange:(NSRange)range {
// 创建自定义附件标注
NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
NSAttributedString *attachmentString = [NSAttributedString attributedStringWithAttachment:attachment];
[textView.textStorage insertAttributedString:attachmentString atIndex:range.location];
// 添加自定义属性
[textView.textStorage addAttributes:@{NSForegroundColorAttributeName: [NSColor redColor]} range:range];
}
Swift
func addCustomMark(at range: NSRange) {
// 创建自定义附件标注
let attachment = NSTextAttachment()
let attachmentString = NSAttributedString(attachment: attachment)
textView.textStorage?.insert(attachmentString, at: range.location)
// 添加自定义属性
textView.textStorage?.addAttributes([.foregroundColor: NSColor.red], range: range)
}
5. 处理空格键和回车键
可以自定义处理空格键和回车键,实现更灵活的输入行为。
Objective-C
- (BOOL)textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector {
if (commandSelector == @selector(insertNewline:)) {
// 自定义处理回车键
NSLog(@"Return key pressed");
return YES;
} else if (commandSelector == @selector(insertTab:)) {
// 自定义处理Tab键
NSLog(@"Tab key pressed");
return YES;
}
return NO;
}
Swift
override func textView(_ textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
if commandSelector == #selector(insertNewline(_:)) {
// 自定义处理回车键
print("Return key pressed")
return true
} else if commandSelector == #selector(insertTab(_:)) {
// 自定义处理Tab键
print("Tab key pressed")
return true
}
return false
}
常用工具类封装
下面,我们将封装一个 NSTextView
的工具类,以更灵活地定制 NSTextView
的行为和功能。
Objective-C
@interface NSTextViewHelper : NSObject
@property (nonatomic, strong) NSTextView *textView;
- (instancetype)initWithTextView:(NSTextView *)textView;
- (void)setPlaceholder:(NSString *)placeholder;
- (void)setTextColor:(NSColor *)color;
- (void)setFont:(NSFont *)font;
- (void)setEditable:(BOOL)editable;
- (void)setSelectable:(BOOL)selectable;
- (void)highlightOccurrencesOfString:(NSString *)searchString;
- (void)addCustomMarkAtRange:(NSRange)range;
- (void)setCustomContextMenu;
@end
@implementation NSTextViewHelper
- (instancetype)initWithTextView:(NSTextView *)textView {
self = [super init];
if (self) {
_textView = textView;
}
return self;
}
- (void)setPlaceholder:(NSString *)placeholder {
if ([_textView isKindOfClass:[NSTextView class]]) {
// 当前没有直接设置占位符的方法,可以通过扩展创建占位符效果
}
}
- (void)setTextColor:(NSColor *)color {
[_textView setTextColor:color];
}
- (void)setFont:(NSFont *)font {
[_textView setFont:font];
}
- (void)setEditable:(BOOL)editable {
[_textView setEditable:editable];
}
- (void)setSelectable:(BOOL)selectable {
[_textView setSelectable:selectable];
}
- (void)highlightOccurrencesOfString:(NSString *)searchString {
// 清除之前的高亮效果
[_textView.layoutManager removeTemporaryAttribute:NSBackgroundColorAttributeName forCharacterRange:NSMakeRange(0, _textView.string.length)];
// 查找并高亮指定字符串
NSString *textViewString = _textView.string;
NSRange searchRange = NSMakeRange(0, textViewString.length);
while (searchRange.location < textViewString.length) {
searchRange = [textViewString rangeOfString:searchString options:0 range:searchRange];
if (searchRange.location != NSNotFound) {
// 应用高亮颜色
[_textView.layoutManager addTemporaryAttribute:NSBackgroundColorAttributeName value:[NSColor yellowColor] forCharacterRange:searchRange];
searchRange.location += searchRange.length;
searchRange.length = textViewString.length - searchRange.location;
} else {
break;
}
}
}
- (void)addCustomMarkAtRange:(NSRange)range {
// 创建自定义附件标注
NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
NSAttributedString *attachmentString = [NSAttributedString attributedStringWithAttachment:attachment];
[_textView.textStorage insertAttributedString:attachmentString atIndex:range.location];
// 添加自定义属性
[_textView.textStorage addAttributes:@{NSForegroundColorAttributeName: [NSColor redColor]} range:range];
}
- (void)setCustomContextMenu {
[_textView setMenu:[self customMenu]];
}
- (NSMenu *)customMenu {
NSMenu *menu = [[NSMenu alloc] initWithTitle:@"ContextMenu"];
[menu addItemWithTitle:@"Custom Action" action:@selector(customAction:) keyEquivalent:@""];
[menu addItemWithTitle:@"Another Action" action:@selector(anotherAction:) keyEquivalent:@""];
return menu;
}
- (void)customAction:(id)sender {
NSLog(@"Custom action triggered");
}
- (void)anotherAction:(id)sender {
NSLog(@"Another action triggered");
}
@end
Swift
class NSTextViewHelper {
private weak var textView: NSTextView?
init(textView: NSTextView) {
self.textView = textView
}
func setPlaceholder(_ placeholder: String) {
if let textView = textView {
// 当前没有直接设置占位符的方法,可以通过扩展创建占位符效果
}
}
func setTextColor(_ color: NSColor) {
textView?.textColor = color
}
func setFont(_ font: NSFont) {
textView?.font = font
}
func setEditable(_ editable: Bool) {
textView?.isEditable = editable
}
func setSelectable(_ selectable: Bool) {
textView?.isSelectable = selectable
}
func highlightOccurrences(of searchString: String) {
guard let textView = textView else { return }
// 清除之前的高亮效果
textView.layoutManager?.removeTemporaryAttribute(.backgroundColor, forCharacterRange: NSRange(location: 0, length: textView.string.utf16.count))
// 查找并高亮指定字符串
let textViewString = textView.string as NSString
var searchRange = NSRange(location: 0, length: textViewString.length)
while let foundRange = textViewString.range(of: searchString, options: [], range: searchRange).toRange() {
// 应用高亮颜色
textView.layoutManager?.addTemporaryAttribute(.backgroundColor, value: NSColor.yellow, forCharacterRange: NSRange(foundRange))
searchRange = NSRange(location: foundRange.upperBound, length: textViewString.length - foundRange.upperBound)
}
}
func addCustomMark(at range: NSRange) {
guard let textView = textView else { return }
// 创建自定义附件标注
let attachment = NSTextAttachment()
let attachmentString = NSAttributedString(attachment: attachment)
textView.textStorage?.insert(attachmentString, at: range.location)
// 添加自定义属性
textView.textStorage?.addAttributes([.foregroundColor: NSColor.red], range: range)
}
func setCustomContextMenu() {
textView?.menu = customMenu()
}
private func customMenu() -> NSMenu {
let menu = NSMenu(title: "ContextMenu")
menu.addItem(withTitle: "Custom Action", action: #selector(customAction(_:)), keyEquivalent: "")
menu.addItem(withTitle: "Another Action", action: #selector(anotherAction(_:)), keyEquivalent: "")
return menu
}
@objc func customAction(_ sender: Any?) {
print("Custom action triggered")
}
@objc func anotherAction(_ sender: Any?) {
print("Another action triggered")
}
}
使用示例
Objective-C
NSTextView *textView = [[NSTextView alloc] initWithFrame:NSMakeRect(0, 0, 400, 300)];
NSTextViewHelper *helper = [[NSTextViewHelper alloc] initWithTextView:textView];
[helper setTextColor:[NSColor blueColor]];
[helper setFont:[NSFont fontWithName:@"Helvetica" size:14]];
[helper setEditable:YES];
[helper highlightOccurrencesOfString:@"NSTextView"];
[helper addCustomMarkAtRange:NSMakeRange(0, 5)];
[helper setCustomContextMenu];
Swift
let textView = NSTextView(frame: NSMakeRect(0, 0, 400, 300))
let helper = NSTextViewHelper(textView: textView)
helper.setTextColor(.blue)
helper.setFont(NSFont(name: "Helvetica", size: 14)!)
helper.setEditable(true)
helper.highlightOccurrences(of: "NSTextView")
helper.addCustomMark(at: NSRange(location: 0, length: 5))
helper.setCustomContextMenu()
将来的你会感谢今天如此努力的你!
版权声明:本文为博主原创文章,未经博主允许不得转载。