NSTextFinder + 以编程方式更改 NSTextView 中的文本

2024-01-11

我有一个 NSTextView,我想使用查找栏。文本可以选择,但不可编辑。我以编程方式更改文本视图中的文本。

当 NSTextFinder 在文本更改后尝试选择下一个匹配项时,此设置可能会崩溃。 NSTextFinder 似乎保留了增量匹配的过时范围。

我尝试了几种更改文本的方法:

[textView setString:@""];

or

NSTextStorage *newStorage = [[NSTextStorage alloc] initWithString:@""];

[textView.layoutManager replaceTextStorage:newStorage];

or

[textView.textStorage beginEditing];
[textView.textStorage setAttributedString:[[NSAttributedString alloc] initWithString:@""]];
[textView.textStorage endEditing];

仅replaceTextStorage:调用-[NSTextFinder noteClientStringWillChange]。以上都不会调用 -[NSTextFinder cancelFindIndicator]。

即使 NSTextFinder 通知了文本更改,它也可能在查找下一个(命令-G)时崩溃。

我还尝试创建自己的 NSTextFinder 实例这篇文章中建议的 https://stackoverflow.com/questions/13839265/nstextfinder-set-search-string-and-clear-visual-feedback-programatically。即使 NSTextView 没有实现 NSTextFinderClient 协议,它也能正常工作并失败,就像没有 NSTextFinder 实例一样。

将 NSTextFinder 与 NSTextView 一起使用的正确方法是什么?


我的应用程序中的文本视图也遇到了同样的问题,更令人烦恼的是,您在互联网上找到的所有“解决方案”要么不正确,要么至少不完整。这是我的贡献。

当你设置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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

NSTextFinder + 以编程方式更改 NSTextView 中的文本 的相关文章

  • 调度队列:如何判断它们是否正在运行以及如何停止它们

    我只是在玩 GCD 并且编写了一个 CoinFlipper 玩具应用程序 抛硬币的方法如下 void flipCoins NSUInteger nFlips Create the queues for work dispatch queue
  • 给 NSWindow 一个背景图片

    好的 我已经在 Photoshop 中创建了一个图像 该图像将与我的应用程序上的按钮对齐 现在我想将其作为窗口的背景图像 以便图像上的字符将对应于我的应用程序上的按键应用程序 我一直在开发的一个小型计算器演示应用程序 基本上 我没有给按钮提
  • 如何创建无法创建新文档的基于文档的应用程序?

    我有一个基于文档的应用程序 旨在处理现有文档 而不是创建新文档 如何防止应用程序在通过 Finder 打开应用程序时创建新的空白文档 您可以实现一个 NSApplication 委托协议方法 BOOL applicationShouldOp
  • 如何使用 iPhone 将照片上传到服务器?

    我正在编写一个 iPhone 应用程序 它可以拍摄照片然后将其上传到服务器 如何使用 Cocoa 将照片上传到服务器 我想我在某处使用 NSUrl Thanks Header interface EPUploader NSObject NS
  • 使用 PRODUCT_NAME 构建 cocoapods 项目的 xcodebuild 失败

    我可以使用以下命令构建我的 Cocoapods 项目 base basename xcworkspace xcworkspace xcodebuild sdk iphonesimulator ios version CONFIGURATIO
  • 在基于视图的 NSTableView 中,如何通过单击使控件成为第一响应者?

    基于视图的 NSTableView 似乎只有标准行为 为了使表内的文本字段成为第一响应者 用户必须双击或单击并 保持冷静 然而 考虑到基于视图的 NSTableViews 提供的灵活性 这种行为并不总是可取的 因为现在可能有很多不同且复杂的
  • Cocoa - 在另一个 xib 上显示 xib

    谁能告诉我如何 或指导我有关信息 在另一个 xib 笔尖 上显示 xib 笔尖 我希望如何放置它 以便我可以以编程方式将它移动到主笔尖 就像这样 这显然不起作用 void drawRect NSRect dirtyRect NSRect c
  • 如何从 Xcode 4 中的实体创建用户界面?

    我已经用核心数据进行了几天的实验 并且在过去的几个小时里尝试找出如何从 xcode 4 中的实体创建 UI 根据我一直在阅读的书籍 您必须选择将核心数据实体拖到界面生成器中的窗口中 但是当我在 xcode 4 中执行此操作时 没有任何反应
  • 使用 Swift 创建 NSAlert

    我有在 Objective C 中创建和 NSAlert 的代码 但我现在想在 Swift 中创建它 该警报旨在确认用户想要删除文档 我想要 删除 按钮来运行删除功能 而 取消 按钮只是为了消除警报 我怎样才能用 Swift 写这个 NSA
  • 获取本周的第一天和最后一天

    如何获取本周的第一天和最后一天 我需要的是某种方法来过滤一组具有 NSDate 属性的对象 只留下本周出现的对象 然后按天过滤它们 我还需要一些方法来获取本地化的日期名称 我尝试使用 NSCalendar NSDate 和 NSDateCo
  • Cocoa 基于文档的应用程序中的 MVC

    我目前正在对我的应用程序进行重构和重组 我意识到模型和视图及其控制器之间的一些分离已经减少 我希望进行一些清理 我的应用程序中使用了几个关键类 NSPersistentDocument NSWindowController 和模型类 NSP
  • 为每行 NSTableView 文本着色

    我有一个 NSTableView 它显示我拥有的对象数组 对于每个对象 行 我想根据在每个对象上运行的函数的结果来更改显示的文本的颜色 因此 例如表中存在于另一个列表 或其他一些要求 中的所有对象 我想以绿色文本显示它们 不存在的对象以红色
  • iOS 使用 NSColor 与 UIColor?

    有什么区别UIColor and NSColor 什么时候会使用每一种 我碰到NSColor在试图弄清楚的同时UIColor用于 iOS 中的属性字符串 我理解使用UIColor对于 UIKit 等 但我不认为NSColor对于这种事情确实
  • WiFi 网络变化是否有 NSNotificationCenter 通知?

    我想在我的 Cocoa 应用程序中订阅 WiFi 网络更改 但我无法找到合适的事件来订阅 WiFi 网络变化是否有 NSNotificationCenter 通知 据我所知 我会用CoreWLAN https developer apple
  • 获取 Mojave 上的鼠标坐标

    我有一个非常基本的小命令行应用程序 可以在下次单击鼠标时获取鼠标坐标 import
  • 准确地从屏幕上的像素获取颜色并转换其颜色空间

    我需要从屏幕上的像素获取颜色并转换其颜色空间 我遇到的问题是 将值与数字色度计应用程序进行比较时 颜色值不相同 create a 1x1 image at the mouse position if let image CGImage CG
  • NSView 中 CALayers 的简单示例

    我正在尝试将多个 CALayer 添加到 NSView 但显示时我的视图仍然为空 这是我的代码 id initWithFrame NSRect frame self super initWithFrame frame if self sel
  • Swift 和 inout 参数中闭包的变量捕获

    我注意到 当 Swift 中的闭包捕获变量时 闭包实际上可以修改该值 这对我来说似乎很疯狂 也是一种获得可怕错误的绝佳方法 特别是当同一个 var 被多个闭包捕获时 var capture Hello captured func g thi
  • 当前收据无效或不匹配的 ds 人员 ID

    我正在尝试测试 MacOS 的应用内购买 输入测试用户凭据后 App Store 抱怨 当前收据无效或 ds 人员 ID 不匹配 并且购买失败 我尝试了很多方法来解决这个问题 获取 App Store 收据 http www kotanco
  • 如何使用 iconutil 手动创建 icns 文件?

    当我验证我的应用程序时 出现此错误 应用程序包不包含 ICNS 格式的图标 同时包含512x512 and a 512x512 2x image 我用来制作 icns 图标Img2icns http www img2icnsapp com

随机推荐