I'd building an app that uses hashtags, like Twitter or Tweetbot. When you're typing a message, if you type the hashtag symbol, I'd like to suggest tags that match the current one you're typing.
I've already figured out how to get the UITableView to appear and show a list of hashtags, but what I can't figure out is how to do the following:
NSRange
of the current word being typed,NSRegularExpression @"#\\w\\w*"
)Can anyone help me with steps 1 and 2? I've been thinking about using textViewDidChange:
, but I'm concerned that the app's performance might suffer if I'm constantly running methods every time the characters change.
Thanks!
to mention or introduce (an idea, proposition, plan, etc.) for consideration or possible action: The architect suggested that the building be restored. to propose (a person or thing) as suitable or possible for some purpose: We suggested him for president.
We can use suggest with the -ing form of a verb when we mention an action but do not mention the person who will do it, because it is understood in the context: She suggested travelling together for safety, since the area was so dangerous.
If you suggest something, you put forward a plan or idea for someone to think about. If you suggest the name of a person or place, you recommend them to someone. If you suggest that something is the case, you say something which you believe is the case.
Regular verb: suggest - suggested - suggested.
I figured it out! I wound up using the textViewDidChange:
and textViewDidChangeSelection:
methods.
To get the NSRange
of the current hashtag being typed, I ran a for
loop over the NSRegularExpression
matches in the text string. From there, I used NSLocationInRange
to find out if the current cursor position intersected any of the hashtags.
Here's the code:
//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;
}
}
The StringChecker
class is a custom one that I wrote, it just has class methods that parse the strings. I made StringChecker
a class because the methods are used in several places in the app. Here's the method:
#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;
}
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