string - 如何实现在键入要搜索的字符串时查找一个字符串在另一个字符串中的所有位置?

标签 string macos swift cocoa

我想在我的应用程序中具有以下功能:

当我同时在我的 TableView 的 NSTextView 窗口中为每种 enzyme 键入 DNA 序列(字符串)时(每个代表小字符串),用户立即看到与每种 enzyme 对应的找到的位点(字符串)的数量( 0 或任何数字)。

我有一个函数,可以用来在字符串中查找字符串的所有可能位置(返回 NSRanges 数组)。在我的例子中,这将在 DNA 序列(字符串)中找到每种 enzyme 对应的所有可能位点(字符串 NSRanges)。

因此,又一次,问题是如何实现这个功能:在键入一个字符串以查找该字符串中的所有站点(以 NSRanges 数组的形式)并将找到的站点的数字相应地放入表中时 enzyme 。

换句话说,返回 enzyme 位点位置的 NSRanges 数组的函数应该自动启动。

更新

我是 cocoa 的新手,根据 R Menke 的建议(我把他的代码行放在代码下面)我有更多可能是愚蠢的问题。我有一个 Controller 类作为 NSWindowController 的子类。我无法将 R Menke 中的代码放入此类(请参阅下面的错误)。而且,在我的 Controller 类中,我有我的 NSTextView,用户可以在其中输入文本作为 @IBOutlet,我应该使用它吗?我应该制作另一个 Controller 文件吗?下面的代码和错误。

import Cocoa
//Error. Multiple inheritance from classes 'NSWindowController' and   'NSViewController'
class AllUnderControl: NSWindowController, NSViewController,NSTextViewDelegate
{
override var windowNibName: String?
{
return "AllUnderControl"
}

override func windowDidLoad() {
    super.windowDidLoad()
}
 //Error. Instance member 'inputDnaFromUser' cannot be used on type 'AllUnderControl'
var textView = inputDnaFromUser(frame: CGRectZero)

 //Error. Method does not override any method from its superclass
override func viewDidLoad() {
    textView.delegate = self
}

func textDidChange(notification: NSNotification) {
    // trigger your function
}

@IBOutlet var inputDnaFromUser: NSTextView!

更新 2 在阅读了两个 Controller 的描述:NSWindowController 和 NSViewController 之后,我在下面进行了以下更改。触发功能是否正确?

import Cocoa

class AllUnderControl: NSWindowController, NSTextViewDelegate
{
override var windowNibName: String?
{
return "AllUnderControl"
}

override func windowDidLoad() {
    super.windowDidLoad()
    inputDnaFromUser.delegate = self
}

func textDidChange(notification: NSNotification) {

    // trigger your function
}

@IBOutlet var inputDnaFromUser: NSTextView! = NSTextView(frame: CGRectZero)

最佳答案

如果您问:“当有人在 NSTextView 中键入内容时,我如何触发一个函数?”

实现一个 NSTextViewDelegate 将您的 NSTextView 的委托(delegate)设置为 self 并在 textDidChange 中触发您的函数。 NSTextViewDelegate 具有一组将由用户交互触发的函数。因此当相应的 Action 发生时,它们内部的代码将被执行。

我建议为此使用 NSViewController 而不是 NSWindowController。 NSWindowController 用于管理 NSViewController。 NSViewController 更适合放置按钮和文本字段等内容。

NSWindowController vs NSViewController

class ViewController: NSViewController, NSTextViewDelegate {


    @IBOutlet var inputDnaFromUser: NSTextView!


    override func viewDidLoad() {
        super.viewDidLoad()

        inputDnaFromUser.delegate = self

    }

    override var representedObject: AnyObject? {
        didSet {
        // Update the view, if already loaded.
        }
    }

    func textDidChange(notification: NSNotification) {
        print("editing stuff")
    }
}

如果您问:“我怎样才能找到一个字符串在另一个字符串中所有出现的地方?”

这将返回一个范围数组。该数组的计数显然是出现的次数。

另一种选择是使用 enumerateSubstringsInRange,如@Russel 的回答所述。我总是更喜欢编写自己的循环。

let string = "The sky is blue today, super blue"
let searchString = "blue"

var ranges: [NSRange] = []

var copyString = NSMutableString(string: string)

while copyString.containsString(searchString) {
    ranges.append(copyString.rangeOfString(searchString))

    guard let lastRange = ranges.last else {
        break
    }
    var replaceString = ""
    for _ in 0..<lastRange.length { replaceString += "$" } // unnalowed character

    copyString.replaceCharactersInRange(lastRange, withString: replaceString)

}

如评论中所建议: 一种更快的方法。

let string : NSString = "The sky is blue today, super blue"
let searchString = "blue"

var ranges: [NSRange] = []

var searchRange : NSRange = NSRange(location: 0, length: string.length)
var lastFoundRange : NSRange = string.rangeOfString(searchString, options: NSStringCompareOptions.LiteralSearch, range: searchRange)

while lastFoundRange.location != NSNotFound {

    ranges.append(lastFoundRange)

    let searchRangeLocation = lastFoundRange.location + lastFoundRange.length
    let searchRangeLength = string.length - searchRangeLocation
    searchRange = NSRange(location: searchRangeLocation, length: searchRangeLength)

    lastFoundRange = string.rangeOfString(searchString, options: NSStringCompareOptions.LiteralSearch, range: searchRange)
}

您将希望在后台队列中执行此操作。但这很快就会变得棘手。一种 enzyme 可以是前一时刻的一种,下一时刻就会发生变化。因此,您需要对输入的每个字符完成所有工作。

一种可能的解决方案是在键入字符时取消每个正在进行的搜索。如果它在键入下一个字符之前完成,您会得到结果。

这是一个 iOS word highlighter我写的实现了这个逻辑。除了使用 UIColor 之外,一切都是纯粹的基础。很容易将其更改为 Cocoa。

关于string - 如何实现在键入要搜索的字符串时查找一个字符串在另一个字符串中的所有位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32890014/

相关文章:

javascript - 使用云代码 Swift 保存到 PFUser

string - 通过替换对数百万个字符串进行分组

java - 在文本文件上多次匹配模式?

macos - 操作系统 : Execute bash script when file appears in folder

ios - Swift - 分组样式 TableView 设计

swift - 如何确定表格 View 中按下按钮的单元格

java - Java 中的 queue.remove() 不工作

c++ - 使用初始值设定项列表从多个字符数组构造 std::string

macos - 在 Sublime Text 2 中,如何在新选项卡中打开新文件?

swift - macOS - NSView 中的背景图像在辅助监视器上消失