为iPhone UITextView打字(如Twitter)时建议#标签

bry*_*ark 6 regex iphone uitextview ios nsregularexpression

我正在构建一个使用主题标签的应用程序,如Twitter或Tweetbot.当您键入消息时,如果您键入主题标签符号,我想建议与您正在键入的当前标签匹配的标签.

我已经想出了如何让UITableView出现并显示一个主题标签列表,但我无法弄清楚如何执行以下操作:

  1. 获取NSRange当前输入的单词,
  2. 查看该范围是否格式化为hashtag(NSRegularExpression @"#\\w\\w*")
  3. (从现在开始,我已经找到代码来搜索匹配的hashtags并在UITableView中显示它们)

任何人都可以帮助我完成步骤1和2吗?我一直在考虑使用textViewDidChange:,但我担心如果每次角色改变时我都在不断运行方法,应用程序的性能可能会受到影响.

谢谢!

bry*_*ark 8

我想到了!我结束了使用textViewDidChange:textViewDidChangeSelection:方法.

为了获取NSRange当前键入的hashtag,我在文本字符串中forNSRegularExpression匹配项上运行了一个循环.从那里,我常常NSLocationInRange发现当前光标位置是否与任何主题标签相交.

这是代码:

//Get the ranges of current hashtags
NSArray *hashtagRanges = [StringChecker rangesOfHashtagsInString:textView.text];
NSTextCheckingResult *currentHashtag;

if ([hashtagRanges count] >0)
{
    //List the ranges of all the hashtags
    for (int i = 0; i<[hashtagRanges count]; i++) 
    {
        NSTextCheckingResult *hashtag = [hashtagRanges objectAtIndex:i];
        //Check if the currentRange intersects the hashtag
        //Have to add an extra space to the range for if you're at the end of a hashtag. (since NSLocationInRange uses a < instead of <=)
        NSRange currentlyTypingHashtagRange = NSMakeRange(hashtag.range.location, hashtag.range.length + 1);
        if (NSLocationInRange(currentRange.location, currentlyTypingHashtagRange))
        {
            //If the cursor is over the hashtag, then snag that hashtag for matching purposes.
            currentHashtag = hashtag;
        }
    }

    if (currentHashtag){
        //If we found one hashtag that we're currently editing

        //Display the hashtag suggester, feed it the current hashtag for matching.
        [self showTagTable];

        //Get the current list of hashtags into an array
        NSFetchRequest *hashtagRequest = [[NSFetchRequest alloc] init];
        NSEntityDescription *tagEntityDescription = [NSEntityDescription entityForName:@"Tags" 
                                                                inManagedObjectContext:self.note.managedObjectContext];
        [hashtagRequest setEntity:tagEntityDescription];
        NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"dateLastUsed" 
                                                                         ascending:YES];
        NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
        [hashtagRequest setSortDescriptors:sortDescriptors];

        NSPredicate *tagPredicate = [NSPredicate predicateWithFormat:@"name contains[c] %@", [noteTextView.text substringWithRange:currentHashtag.range]];
        [hashtagRequest setPredicate:tagPredicate];

        tagsToDisplay = (NSMutableArray *)[self.note.managedObjectContext executeFetchRequest:hashtagRequest error:nil];
        [tagListTable reloadData];

        //If there are no matching hashtags, then let's hide the tag table.
        if ([tagsToDisplay count] == 0) 
        {
            [self hideTagTable];
            return;
        }

    }
Run Code Online (Sandbox Code Playgroud)

这个StringChecker类是我写的一个自定义类,它只有解析字符串的类方法.我创建StringChecker了一个类,因为这些方法在应用程序的几个地方使用.这是方法:

    #pragma mark - Hashtag Methods
+(NSArray *)rangesOfHashtagsInString:(NSString *)string {
    NSRegularExpression *hashtagDetector = [[NSRegularExpression alloc] initWithPattern:@"#\\w\\w*" 
                                                                                options:NSRegularExpressionCaseInsensitive 
                                                                                  error:nil];    
    NSArray *hashtagRanges = [hashtagDetector matchesInString:string
                                                      options:NSMatchingWithoutAnchoringBounds
                                                        range:NSMakeRange(0, string.length)];
    return hashtagRanges;
}

+(NSUInteger)numberOfHashtagsInString:(NSString *)string {
    NSRegularExpression *hashtagDetector = [[NSRegularExpression alloc] initWithPattern:@"#\\w\\w*" 
                                                                                options:NSRegularExpressionCaseInsensitive 
                                                                                  error:nil];
    NSUInteger numberOfHashtags = [hashtagDetector numberOfMatchesInString:string
                                                                   options:NSRegularExpressionCaseInsensitive
                                                                     range:NSMakeRange(0, string.length)];
    return numberOfHashtags;
}
Run Code Online (Sandbox Code Playgroud)