我的应用程序中的文本视图也遇到了同样的问题,更令人烦恼的是,您在互联网上找到的所有“解决方案”要么不正确,要么至少不完整。这是我的贡献。
当你设置textView.useFindBar = YES
在 NSTextView 中,该文本视图在内部创建一个 NSTextFinder,并将搜索/替换命令转发给它。不幸的是, NSTextView 似乎无法正确处理您以编程方式对其关联的 NSTextStorage 所做的更改,这会导致您提到的崩溃。
如果你想改变这种行为,创建你的私有 NSTextFinder 是不够的:你还需要避免文本视图使用其默认的文本查找器,否则会发生冲突,并且新的文本查找器不会有太大用处。
为此,您必须继承 NSTextView 的子类:
@interface MyTextView : NSTextView
- (void) resetTextFinder; // A method to reset the view's text finder when you change the text storage
@end
在文本视图中,您必须重写用于控制文本查找器的响应程序方法:
@interface MyTextView () <NSTextFinderClient>
{
NSTextFinder* _textFinder; // define your own text finder
}
@property (readonly) NSTextFinder* textFinder;
@end
@implementation MyTextView
// Text finder command validation (could also be done in method validateUserInterfaceItem: if you prefer)
- (BOOL) validateMenuItem:(NSMenuItem *)menuItem
{
BOOL isValidItem = NO;
if (menuItem.action == @selector(performTextFinderAction:)) {
isValidItem = [self.textFinder validateAction:menuItem.tag];
}
// validate other menu items if needed
// ...
// and don't forget to call the superclass
else {
isValidItem = [super validateMenuItem:menuItem];
}
return isValidItem;
}
// Text Finder
- (NSTextFinder*) textFinder
{
// Create the text finder on demand
if (_textFinder == nil) {
_textFinder = [[NSTextFinder alloc] init];
_textFinder.client = self;
_textFinder.findBarContainer = [self enclosingScrollView];
_textFinder.incrementalSearchingEnabled = YES;
_textFinder.incrementalSearchingShouldDimContentView = YES;
}
return _textFinder;
}
- (void) resetTextFinder
{
if (_textFinder != nil) {
// Hide the text finder
[_textFinder cancelFindIndicator];
[_textFinder performAction:NSTextFinderActionHideFindInterface];
// Clear its client and container properties
_textFinder.client = nil;
_textFinder.findBarContainer = nil;
// And delete it
_textFinder = nil;
}
}
// This is where the commands are actually sent to the text finder
- (void) performTextFinderAction:(id<NSValidatedUserInterfaceItem>)sender
{
[self.textFinder performAction:sender.tag];
}
@end
在文本视图中,您仍然需要设置属性usesFindBar
and incrementalSearchingEnabled
to YES
.
在更改视图的文本存储(或文本存储内容)之前,您只需调用[myTextView resetTextFinder];
下次您进行搜索时,为您的新内容重新创建一个全新的文本查找器。
如果您想了解有关 NSTextFinder 的更多信息,我见过的最好的文档是OS X 10.7 的 AppKit 发行说明 https://developer.apple.com/library/mac/releasenotes/AppKit/RN-AppKitOlderNotes/index.html#10_7TextFinder