Utilisation de données de base avec un magasin sqlite sur iPhone .... J'ai un tas d'entités d'image de bande dessinée, chacune avec une chaîne qui comprend la question de bande dessinée de #, par exemple: image.imageTitle = @"Issue 12: Special Edition";
Limites de mots ( b) dans NSPredicate provoquant NSFetchRequest pour retourner aucun objet géré
une partie de l'interface utilisateur permet à l'utilisateur de saisir un numéro d'émission pour passer à la question suivante. Mon code initial pour cela était sloooooooow parce que imageAtIndex:
interroge les données de base pour un objet à la fois. Sur plusieurs centaines de numéros, cela peut prendre jusqu'à 40 secondes pour passer la première boucle!
code lent:
// Seek forward from the next page to the right
for (i = currentPage + 1; i < [self numberOfPages]; i++) {
iterationString = [[self imageAtIndex:i] imageTitle];
iterationNumber = [[iterationString stringByTrimmingCharactersInSet:nonDigits] intValue];
if (issueNumber == iterationNumber) {
keepLooking = NO;
break;
}
}
// If nothing was found to the right, seek forward from 0 to the current page
if (i == [self numberOfPages] && keepLooking) {
for (i = 0 ; i < currentPage; i++) {
iterationString = [[self imageAtIndex:i] imageTitle];
iterationNumber = [[iterationString stringByTrimmingCharactersInSet:nonDigits] intValue];
if (issueNumber == iterationNumber) {
keepLooking = NO;
break;
}
}
}
Espérant une solution beaucoup plus efficace, j'ai décidé d'essayer de faire une requête directe sur les données de base comme ceci:
NSString *issueNumber = @"12";
NSString *issueWithWordBoundaries = [NSString stringWithFormat:@"\\b%@\\b",issueNumber];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(groupID == %@) AND (imageTitle CONTAINS %@)", groupID, issueWithWordBoundaries];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"CBImage" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setPredicate:predicate];
[fetchRequest setIncludesSubentities:NO]; // Not sure if this is needed, but just in case....
// Execute the fetch
NSError *error = nil;
NSArray *fetchedObjects = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
// [fetchedImages count] == 0
Entre le Predicate Programming Guide et la ICU regex specs, j'ai pensé que les \ b's aiderait à empêcher la recherche de 12 retournant 120, 121, 122, etc. Au lieu de cela, il ne retourne rien du magasin du tout!
D'autre part, si je laisse hors les limites de mots et rechercher plutôt pour stringWithFormat:@"%@",issueNumber
, je reçois des dizaines d'objets gérés sont revenus, de 12 à 129 à 412.
Ma meilleure estimation à ce stade est que je J'ai rencontré l'un des Constraints and Limitations de Core Data. Sinon, qu'est-ce que je fais de mal? Si oui, existe-t-il une solution qui offre à la fois une correspondance exacte et la vitesse d'un seul fetch?
Corrigez-moi si je me trompe mais il semblerait que vous n'utilisiez pas réellement 'regularExpression', au lieu de faire une recherche CONTAINS en utilisant votre phrase de recherche originale. – taber
Euh, ça ressemble à ça, @taber. Pour dire la vérité, ça fait assez longtemps que je n'ai aucun souvenir du projet, ou quel est le problème. Cette question a eu très peu d'activité en 4 ans, donc je pense que je vais juste l'indiquer pour la suppression. :-) – clozach
Je le laisserais en place, je l'ai trouvé en cherchant à utiliser une correspondance de prédicat avec les limites de mots et ça m'a aidé !! Vous avez juste à faire: '" stringToSearch CONTAINS% @ ", regularExpression' mais j'ai aussi dû d'abord échapper des caractères spéciaux dans' exactPhrase'. – taber