【问题标题】:Line Number for Selected String in TextViewTextView 中所选字符串的行号
【发布时间】:2014-02-03 12:01:04
【问题描述】:

我在 NSTextView 控件中放置了一些文本。好吧,我的文本字符串来自哪里并不重要。因此,我不会将此主题仅限于 OSX。无论如何,我可以找出所选字符串的当前位置...

NSRange sel = [textView1 selectedRange]; // textView1 may be NSTextView or UITextView.
NSNumber *point = [NSNumber numberWithInteger:sel.location];

我怎样才能知道这个选定的字符串属于哪一行?

NSArray *array = [[textView1 string] componentsSeparatedByString:@"\r\n"];

感谢您的帮助。

【问题讨论】:

    标签: objective-c nsstring


    【解决方案1】:

    我认为下面的代码应该做到这一点。 m 是所选字符串所属的行号。它基于数组。所以第一行是 0,而不是 1。 stringContains 只是一个函数,用于查看字符串(在本例中为每一行)是否包含所选段落。对于我需要返回的一个简单数字,有这么多行代码。我不知道这是否是一种更简单的方法。请注意,m 的数据类型设置为“unsigned”,k 设置为“unsigned long”。 k 是所有字符的个数。这个数字和 stringContains 确保 m 是所选段落所属的行。如果总行数大到几千,您可能必须自动释放变量。这是针对 OSX 的。

    - (void)findLineNumber {
        NSRange sel = [textView1 selectedRange];
        NSNumber *point = [NSNumber numberWithInteger:sel.location];
        NSString *selectedText = [[textView1 string] substringWithRange:[textView1 selectedRange]]; // [textView1 string] into textView1.text for iOS
        NSArray *array = [[textView1 string] componentsSeparatedByString:@"\n"]; // [textView1 string] into textView1.text for iOS
    
        unsigned long k = 0;
        unsigned m;
        for (unsigned i2 = 0; i2 < array.count; i2++) {
            NSString *line = [array objectAtIndex:i2];
            if (point.integerValue >= k && [self stringContains:line:selectedText]) {
                m = i2;
            }
            k += line.length;
        }
    
        NSLog(%i,m); // zero-based
    }
    
    - (BOOL)stringContains:(NSString *)source :(NSString *)find {
        // case-sensitive
        NSRange myRange;
        myRange = [source rangeOfString:find];
        if ([source isEqualToString:find]) {
            return true;
        } else {
            if (source.length > find.length) {
                if (myRange.location == NSNotFound) {
                    return false;
                }
                else {
                    return true;
                }
            } else {
                return false;
            }
        }
    }
    

    【讨论】:

    • 选择长为0的情况下不起作用,属于正常情况。
    • 如果没有选择文本段,则由开发人员访问 findLineNumber。
    【解决方案2】:

    你当然不应该使用componentsSeparatedByString:@"\r\n”,而是使用\n。原生文本对象不使用 CRLF,只使用 LF。

    另外,请注意,示例中的 sel.location 只是选择的开始 - 如果选择了多个字符,我不确定您要做什么。

    无论如何,你可能想打电话:

    - (void)getLineStart:(NSUInteger *)startIndex end:(NSUInteger *)lineEndIndex contentsEnd:(NSUInteger *)contentsEndIndex forRange:(NSRange)aRange
    
    Parameters
    startIndex
    Upon return, contains the index of the first character of the line containing the beginning of aRange. Pass NULL if you do not need this value (in which case the work to compute the value isn’t performed).
    lineEndIndex
    Upon return, contains the index of the first character past the terminator of the line containing the end of aRange. Pass NULL if you do not need this value (in which case the work to compute the value isn’t performed).
    contentsEndIndex
    Upon return, contains the index of the first character of the terminator of the line containing the end of aRange. Pass NULL if you do not need this value (in which case the work to compute the value isn’t performed).
    aRange
    A range within the receiver. The value must not exceed the bounds of the receiver.
    Raises an NSRangeException if aRange is invalid.
    

    【讨论】:

    • 谢谢。请原谅,'getLineStart' 与查找所选字符串所属的行有什么关系。
    • 你会向后跳通过文本计数行,一次得到一行 getLineStart:... (你也可以从头开始前进,当所选范围在 startIndex,lineEndIndex 内时停止)
    猜你喜欢
    • 2014-02-08
    • 2022-01-05
    • 2018-05-26
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多