How to use NSTextFinder programmatically?

我与影子孤独终老i 提交于 2019-12-11 04:54:47

问题


I'd like to do a "find" operation in an NSTextView without using the built-in find bar. How can I programmatically set a search string and have the results highlighted inside the text view?

This is for macOS 10.12 and higher.

FWIW, this is not a duplicate of this question: NSTextFinder set search string and clear visual feedback programatically

That question is about programmatically controlling the find bar UI, either clearing previous find results or populating the find bar search field.

This question is about invoking a "find" operation programmatically without using the find bar UI at all.


回答1:


Here's my test code (hacky, experimental):

@interface ViewController ()

@property (strong) NSTextFinder *textFinder;
@property (weak) IBOutlet NSTextView *textView; // find Uses Bar, Incremental Searching is on
@property (weak) NSView *myFindBarView;
@property (weak) IBOutlet NSView *findBarContainerView; // hidden
@property BOOL barVisible;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.textFinder = [[NSTextFinder alloc] init];
    self.textFinder.incrementalSearchingEnabled = YES;
    self.textFinder.incrementalSearchingShouldDimContentView = YES;
    self.textFinder.client = (id<NSTextFinderClient>)self.textView;
    self.textFinder.findBarContainer = self;
    [self.textFinder performAction:NSTextFinderActionShowFindInterface];
}

- (IBAction)testSearchString:(id)sender {
    // action method of a Test button, searches for "found"
    [self.textFinder cancelFindIndicator];

    // search the subviews for a view of class NSSearchField
    __block __weak NSSearchField *(^weak_findSearchField)(NSView *);
    NSSearchField *(^findSearchField)(NSView *);
    weak_findSearchField = findSearchField = ^(NSView *view) {
        if ([view isKindOfClass:[NSSearchField class]])
            return (NSSearchField *)view;
        __block NSSearchField *foundView = nil;
        [view.subviews enumerateObjectsUsingBlock:^(NSView *subview, NSUInteger idx, BOOL *stop) {  
            foundView = weak_findSearchField(subview);
            if (foundView)
                *stop = YES;
        }];
        return foundView;
    };

    NSSearchField *searchField = findSearchField(self.myFindBarView);
    [searchField setStringValue:@"found"];
    // execute the action of the search field to confirm the new value and do a search
    [searchField sendAction:searchField.action to:searchField.target];
    /* add to select all
    [self.textFinder performAction:NSTextFinderActionSelectAll];
    */
}

// NSTextFinderBarContainer

- (void)findBarViewDidChangeHeight {
}

- (NSView *)findBarView {
    return self.myFindBarView;
}

- (void)setFindBarView:(NSView *)theView {
    self.myFindBarView = theView;
    if (theView) {
        NSRect frame = theView.frame;
        frame.size.width = self.findBarContainerView.bounds.size.width;
        theView.frame = frame;
        [self.findBarContainerView addSubview:theView];
    }
}

- (NSView *)contentView {
    return self.textView.enclosingScrollView.contentView;
}

- (BOOL)isFindBarVisible {
    return self.barVisible;
}

- (void)setFindBarVisible:(BOOL)theVisible {
    self.barVisible = theVisible;
}

@end


来源:https://stackoverflow.com/questions/46817490/how-to-use-nstextfinder-programmatically

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!