Sugiera tags # mientras escribe (como Twitter) para iPhone UITextView

Me gustaría build una aplicación que use hashtags, como Twitter o Tweetbot. Cuando está escribiendo un post, si escribe el símbolo del hashtag, me gustaría sugerir tags que coincidan con el actual que está escribiendo.

Ya he descubierto cómo hacer que UITableView aparezca y muestre una list de hashtags, pero lo que no puedo entender es cómo hacer lo siguiente:

  1. Obtenga el NSRange de la palabra actual que se escribe,
  2. Vea si ese range está formateado como un hashtag ( NSRegularExpression @"#\\w\\w*" )
  3. (De aquí en adelante, tengo el código descubierto para search hashtags coincidentes y mostrarlos en UITableView)

¿Alguien puede ayudarme con los pasos 1 y 2? He estado pensando en usar textViewDidChange: pero me preocupa que el performance de la aplicación pueda sufrir si estoy constantemente ejecutando methods cada vez que cambian los personajes.

¡Gracias!

¡Me lo imaginé! Terminé usando los methods textViewDidChange: y textViewDidChangeSelection:

Para get el NSRange del hashtag actual que se escribe, ejecuté un bucle for sobre las coincidencias NSRegularExpression en la cadena de text. A partir de ahí, utilicé NSLocationInRange para averiguar si la position actual del cursor interceptaba cualquiera de los hashtags.

Aquí está el código:

 //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]; NSPnetworkingicate *tagPnetworkingicate = [NSPnetworkingicate pnetworkingicateWithFormat:@"name contains[c] %@", [noteTextView.text substringWithRange:currentHashtag.range]]; [hashtagRequest setPnetworkingicate:tagPnetworkingicate]; 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; } } 

La class StringChecker es una personalizada que escribí, solo tiene methods de class que analizan las cadenas. Hice StringChecker una class porque los methods se usan en varios lugares de la aplicación. Aquí está el método:

  #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; } 

Otra forma en que pensé hacer esto es la siguiente.

En la - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text function de - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text Puse un listener para un # que se escribe y comienza a grabar los caracteres siguiendo el hash hasta que el usuario escriba un espacio momento en que se restablece.

 if ([text isEqualToString:@"#"]) { recordingHashTag = YES; startParse = range.location; }else if ([text isEqualToString:@" "]) { currentHashTag = nil; recordingHashTag = NO; theTable.hidden = YES; } if (recordingHashTag == YES) { NSString *value; if (startParse > [textView.text length] - startParse) { value = [textView.text substringWithRange:NSMakeRange(startParse, [textView.text length] - startParse)]; [self filterHashTagTableWithHash:value]; } } 

Si BOOL recordingHashTag está configurado en YES , pase la substring contiene el text de hashtag a una function que busca una matriz de hashtags pre-poblada. Si hay una coincidencia, agrega esa input a una matriz filtrada de hashtags que usa para poblar la tableview de tableview sobre la marcha.

 -(void)filterHashTagTableWithHash:(NSString *)hash{ [self.filterHashTagArray removeAllObjects]; for (NSString *hashTag in self.hashTagArray ){ NSRange result = [hashTag rangeOfString:hash options:NSCaseInsensitiveSearch]; if (result.location != NSNotFound) { [filterHashTagArray addObject:hashTag]; } } if (filterHashTagArray.count) { theTable.hidden = NO; }else{ theTable.hidden = YES; } [self.theTable reloadData]; } 

El último paso es insert la label hash cuando el usuario hace clic en la input de la tabla.

  - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewCell *cell = (UITableViewCell*)[self tableView:theTable cellForRowAtIndexPath:indexPath]; NSString *newString = [textViewComment.text stringByReplacingCharactersInRange:NSMakeRange(startParse, [textViewComment.text length] - startParse) withString:cell.textLabel.text]; textViewComment.text = newString; } 

Simplemente no se olvide de borrar sus variables cuando un usuario retrocede la mitad de la label hash.