I have some text placed in an NSTextView control. Well, where my text string comes from is not important. So I won't restrict this topic only to OSX. Anyway, I can find out the current position of the selected string like...
NSRange sel = [textView1 selectedRange]; // textView1 may be NSTextView or UITextView.
NSNumber *point = [NSNumber numberWithInteger:sel.location];
How can I find out which line this selected string belongs to?
NSArray *array = [[textView1 string] componentsSeparatedByString:@"\r\n"];
Thank you for your help.
I think the following code should do it. m is the line number to which the selected string belongs. It's based on an array. So the first line is 0, not 1. stringContains is just a function for seeing if the string (in this case, each line) contains the selected passage. There are so many lines of code for a simple number I need to return. I don't know if it's a simpler way of doing it. Note that the data type of m is set to 'unsigned' and k to 'unsigned long.' k is the number of all characters. This number and stringContains make sure that m is the line to which the selected passage belongs. If the total number of lines is large like several thousands, you may have to auto-release variables. That's for 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;
}
}
}
You certainly shouldn’t use componentsSeparatedByString:@"\r\n”, just use \n. Native texts objects don’t use CRLF, the just use LF.
Also, note that the sel.location in your example is just the beginning of the selection—I’m not sure what you want to do if multiple characters are selected.
Anyhow, you probably want to call:
- (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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With