在NSTextField中查找单词的rect / position

时间:2016-01-07 05:25:31

标签: swift macos nstextfield

我有一个NSTextField,里面有一个句子。我想为句子中的每个单词找到一个rect(理想情况下)或位置,以便在那些位置(NSTextField之外)执行操作。

使用NSLayoutManager.boundingRectForGlyphRange在NSTextView / UITextView seems achievable中执行此操作,但没有NSTextView(和UITextView)所具有的NSLayoutManager似乎更具挑战性。

在NSTextField中查找给定单词位置的最佳方法是什么?

2 个答案:

答案 0 :(得分:5)

它需要一个几乎没有记录的魔法和另一个完全没有记录的位。这是Objective-C代码。不要在Swift中使用它,对不起。

<div ng-form="forms.motorForm">

NSRect textBounds = [textField.cell titleRectForBounds:textField.bounds]; NSTextContainer* textContainer = [[NSTextContainer alloc] init]; NSLayoutManager* layoutManager = [[NSLayoutManager alloc] init]; NSTextStorage* textStorage = [[NSTextStorage alloc] init]; [layoutManager addTextContainer:textContainer]; [textStorage addLayoutManager:layoutManager]; textContainer.lineFragmentPadding = 2; layoutManager.typesetterBehavior = NSTypesetterBehavior_10_2_WithCompatibility; textContainer.containerSize = textBounds.size; [textStorage beginEditing]; textStorage.attributedString = textField.attributedStringValue; [textStorage endEditing]; NSUInteger count; NSRectArray rects = [layoutManager rectArrayForCharacterRange:matchRange withinSelectedCharacterRange:matchRange inTextContainer:textContainer rectCount:&count]; for (NSUInteger i = 0; i < count; i++) { NSRect rect = NSOffsetRect(rects[i], textBounds.origin.x, textBounds.origin.y); rect = [textField convertRect:rect toView:self]; // do something with rect } 已记录在案heretypesetterBehavior是根据经验确定的。

根据您计划对矩形进行的确切操作,您可能希望将lineFragmentPadding作为所选字符范围传递。

为了提高效率,您通常希望保留文本对象,而不是每次都实例化它们。您只需将文本容器的{ NSNotFound, 0 }和文本存储的containerSize设置为适当的值。

答案 1 :(得分:0)

根据肯·托马斯(Ken Thomases)的回答。我改编了Swift 4.2

    guard let textFieldCell = textField.cell,
        let textFieldCellBounds = textFieldCell.controlView?.bounds else{
        return
    }
    let textBounds = textFieldCell.titleRect(forBounds: textFieldCellBounds)
    let textContainer = NSTextContainer()
    let layoutManager = NSLayoutManager()
    let textStorage = NSTextStorage()

    layoutManager.addTextContainer(textContainer)
    textStorage.addLayoutManager(layoutManager)

    layoutManager.typesetterBehavior = NSLayoutManager.TypesetterBehavior.behavior_10_2_WithCompatibility

    textContainer.containerSize = textBounds.size
    textStorage.beginEditing()
    textStorage.setAttributedString(textFieldCell.attributedStringValue)
    textStorage.endEditing()

    let rangeCharacters = (textFieldCell.stringValue as NSString).range(of: "string")

    var count = 0
    let rects: NSRectArray = layoutManager.rectArray(forCharacterRange: rangeCharacters,
                                                    withinSelectedCharacterRange: rangeCharacters,
                                                    in: textContainer,
                                                    rectCount: &count)!

    for i in 0...count {
        var rect = NSOffsetRect(rects[i], textBounds.origin.x, textBounds.origin.y)
        rect = textField.convert(rect, to: self.view)
       // do something with rect
    }

归功于Ken Thomases

相关问题