1

I need to highlight words in my UITextView one by one. How do I get the NSRange values of all the words of a UITextView and store them in an NSArray?

Ashish Kakkad
  • 23,586
  • 12
  • 103
  • 136
enigma
  • 865
  • 9
  • 22
  • What you tried so far? – Ashish Kakkad May 28 '15 at 06:53
  • I thought of tokenizing the string in my `UITextView` and saving it in an array and finding the range corresponding to every string in that array. But it wouldn't work in case of many occurrences of a particular string. – enigma May 28 '15 at 07:00
  • @y0ter9a: I added a possible solution that uses what you describe, with support for multiple occurences – rdurand May 28 '15 at 07:27

3 Answers3

4

You can use this method of NSString - enumerateSubstringsInRange:options:usingBlock:, and use NSStringEnumerationByWords for option. It will iterate over all words of your string and give you the range of it, that you can save into an array.

NSString *string = @"How do I get the NSRange values of all the words of a UITextView in an array";

NSMutableArray *words = [NSMutableArray array];
NSMutableArray *ranges = [NSMutableArray array];

[string enumerateSubstringsInRange:NSMakeRange(0, [string length])
                           options:NSStringEnumerationByWords
                        usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
                            [words addObject:substring];
                            [ranges addObject:[NSValue valueWithRange:substringRange]];
                        }
 ];

NSLog(@"Words:\n%@", words);
NSLog(@"Ranges:\n%@", ranges);
pteofil
  • 4,133
  • 17
  • 27
  • I read the documentation, but couldn't understand _where_ and _how_ I would get the range of the words that this function iterates over. Could you please give a brief explanation? – enigma May 28 '15 at 07:22
  • Clean solution, I didn't know this method! +1 – rdurand May 28 '15 at 08:47
  • Thanks a lot. I ended up doing the same thing after researching a bit and when I came back here, I saw your edited answer and this was exactly what I needed. :) – enigma May 28 '15 at 08:49
2

Edit: this solution works well but is kind of the "hard way", and crashes in case of double spaces in the original string. @pteofil's solution using enumerateSubstringsInRange:options:usingBlock: is cleaner.


This should do the work, even with duplicate words in the string:

// Your original text, which you should access with myTextView.text
NSString *text = @"Hello world this is a text with duplicated text string inside";

// Arrays to store separate words and ranges
NSArray *words = [text componentsSeparatedByString:@" "];
NSMutableArray *ranges = [NSMutableArray array];

// The search range, in case your text contains duplicated words
NSRange searchRange = NSMakeRange(0, text.length);

// Loop on the words
for (NSString *word in words) {

    // Get the range of the word, /!\ in the search range /!\
    NSRange range = [text rangeOfString:word options:NSLiteralSearch range:searchRange];
    // Store it in an NSValue, as NSRange is not an object
    // (access the range later with aValue.rangeValue
    [ranges addObject:[NSValue valueWithRange:range]];
    // Set your new search range to after the last word found, to avoid duplicates
    searchRange = NSMakeRange(range.location + range.length, text.length - (range.location + range.length));
}

// Logging the results
NSLog(@"Text:\n%@", text);
NSLog(@"Words:\n%@", words);
NSLog(@"Ranges:\n%@", ranges);

This gives the following output:

Text: 
Hello world this is a text with duplicated text string inside

Words:
(
    Hello,
    world,
    this,
    is,
    a,
    text,
    with,
    duplicated,
    text,
    string,
    inside )

Ranges:
(
    "NSRange: {0, 5}",
    "NSRange: {6, 5}",
    "NSRange: {12, 4}",
    "NSRange: {17, 2}",
    "NSRange: {20, 1}",
    "NSRange: {22, 4}",
    "NSRange: {27, 4}",
    "NSRange: {32, 10}",
    "NSRange: {43, 4}",
    "NSRange: {48, 6}",
    "NSRange: {55, 6}" )
rdurand
  • 7,342
  • 3
  • 39
  • 72
  • This works, but crashes if you have double spaces, i suggest trimming your text first.. :) – 0yeoj May 28 '15 at 08:10
  • 1
    @0yeoj: nice catch, I'll try to secure the code for this issue – rdurand May 28 '15 at 08:27
  • 1
    Your answer works, therefore the upvote. But I ended up using @pteofil's solution, because it's clean and simple as you've said yourself. – enigma May 28 '15 at 08:50
-1

If you are planning to get the array after hitting the "Return" key then use textfield delegate method

-(void)textFieldDidEndEditing:(UITextField *)textField{
NSArray *allwords = [textField.text componentsSeparatedByString:@" "];
}
Saheb Roy
  • 5,899
  • 3
  • 23
  • 35