Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The left hand side for an ALL or ANY operator must be either an NSArray or an NSSet

The app I have just taken over is crashing at random times with the "The left hand side for an ALL or ANY operator must be either an NSArray or an NSSet" error.

The app when crashing is trying to read from Core Data. It doesn't crash all the time, just randomly. I am not sure if its the PREDICATE causing the issue or two threads access Core Data? If it were the PREDICATE, I would think it would crash every time. Their have been several migrations to the db structure so maybe one of the migrations has left an object in a weird state and its crashing when that object is ever fetched by Core Data?

Here are the predicate calls

+(NSString *)buildCompoundContainsStringForField:(NSString *)field searchTerm:(NSString *)search operator:(NSString *)operator
{
NSArray *parts = [search componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSString *partJoin = [NSString stringWithFormat:@"'%@ %@ contains[c]'", operator, field];
NSString *compoundContains = [parts componentsJoinedByString:partJoin];
NSString *predicateString = [NSString stringWithFormat:@"%@ contains[c] '%@'", field, compoundContains];
return predicateString;
}



    NSPredicate *titleSearch = [AStore searchTitlePredicate:search];
    NSPredicate *ingredientSearch = [AStore searchIngredientsPredicate:search];
    NSPredicate *recipeDecription = [AStore searchDescriptionPredicate:search];
    NSPredicate *searchMethod = [AStore searchMethodPredicate:search];


+ (NSPredicate *)searchIngredientsPredicate:(NSString *)search {
return [NSPredicate predicateWithFormat:[self buildCompoundContainsStringForField:@"ANY ingredients.desc"
                                                                       searchTerm:search
                                                                         operator:@"AND"]];
}

+ (NSPredicate *)searchTitlePredicate:(NSString *)search {
return [NSPredicate predicateWithFormat:[self buildCompoundContainsStringForField:@"ANY title"
                                                                       searchTerm:search
                                                                         operator:@"AND"]];
}

+ (NSPredicate *)searchDescriptionPredicate:(NSString *)search {
return [NSPredicate predicateWithFormat:[self buildCompoundContainsStringForField:@"ANY recipeDescription"
                                                                       searchTerm:search
                                                                         operator:@"AND"]];
}

+ (NSPredicate *)searchMethodPredicate:(NSString *)search {
return [NSPredicate predicateWithFormat:[self buildCompoundContainsStringForField:@"ANY method"
                                                                       searchTerm:search
                                                                         operator:@"AND"]];
}

=== METHOD WHERE ITS CRASHING ======

-(void) updateDictionaryWithWeight:(int)weight usingRequest:(NSFetchRequest *)request
{
    NSError *error;
    NSArray *results = [self.context executeFetchRequest:request error:&error];  <---- CRASHES/ERRORS HERE

......

}

=== HERE IS THE CALL STACK ====

    *** First throw call stack:
    (
        0   CoreFoundation                      0x0000000103fbb495 __exceptionPreprocess + 165
        1   libobjc.A.dylib                     0x0000000103d1a99e objc_exception_throw + 43
        2   Foundation                          0x000000010351606b -[NSPredicateOperator performOperationUsingObject:andObject:] + 826
        3   Foundation                          0x0000000103515c1e -[NSComparisonPredicate evaluateWithObject:substitutionVariables:] + 314
        4   Foundation                          0x0000000103515ae2 -[NSPredicate evaluateWithObject:] + 19
        5   CoreData                            0x0000000101df40aa -[NSManagedObjectContext executeFetchRequest:error:] + 2170
        6   CoreData                            0x0000000101e3b18b -[NSManagedObjectContext(_NestedContextSupport) _parentObjectsForFetchRequest:inContext:error:] + 395
        7   CoreData                            0x0000000101ea5ed3 __82-[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:]_block_invoke + 563
        8   libdispatch.dylib                   0x00000001042ef72d _dispatch_client_callout + 8
        9   libdispatch.dylib                   0x00000001042de5d0 _dispatch_barrier_sync_f_invoke + 57
        10  CoreData                            0x0000000101e3af92 _perform + 114
        11  CoreData                            0x0000000101e3ae2d -[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:] + 301
        12  CoreData                            0x0000000101df3a21 -[NSManagedObjectContext executeFetchRequest:error:] + 497
        13  Things                             0x000000010035ff40 -[AStore updateDictionaryWithWeight:usingRequest:] + 128
        14  Things                             0x000000010035cce8 -[AStore weightedThingsWithSearchString:andFilterFlags:sortedBy:] + 920
        15  Things                             0x00000001003b87a7 -[ASearchViewController doSearchWithCompletionBlock:] + 1319
        16  Things                             0x00000001003be466 -[ASearchViewController localRefresh:] + 198
        17  Things                             0x00000001003c17e1 __59-[ASearchViewController filterControllerDidFinish:]_block_invoke + 577
        18  Things                             0x000000010059624e __72+[UIView(mfw) presentIndicatorWithLoadingTitle:successTitle:completion:]_block_invoke + 174
        19  libdispatch.dylib                   0x00000001042dc851 _dispatch_call_block_and_release + 12
        20  libdispatch.dylib                   0x00000001042ef72d _dispatch_client_callout + 8
        21  libdispatch.dylib                   0x00000001042df3fc _dispatch_main_queue_callback_4CF + 354
        22  CoreFoundation                      0x0000000104019289 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
        23  CoreFoundation                      0x0000000103f66854 __CFRunLoopRun + 1764
        24  CoreFoundation                      0x0000000103f65d83 CFRunLoopRunSpecific + 467
        25  GraphicsServices                    0x0000000104b2bf04 GSEventRunModal + 161
        26  UIKit                               0x0000000102493e33 UIApplicationMain + 1010
        27  Things                             0x0000000100002463 main + 115
        28  libdyld.dylib                       0x00000001045405fd start + 1
        29  ???                                 0x0000000000000001 0x0 + 1
    )
    libc++abi.dylib: terminating with uncaught exception of type NSException
like image 524
jdog Avatar asked Jun 17 '14 17:06

jdog


1 Answers

The problem is that the ANY operator is not needed here. As Martin R mentioned, ANY is used with to-many relationships. So if you have something like:

class Recipe
{
  public String title;
}

class CookBook
{
 public Array recipes;
}

and you want to find all the CookBooks that have a Recipe with a certain title then you would use predicate:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY recipes.title CONTAINS[c] %@", @"sh"];

If you just want all the Recipe objects that match your title then the ANY operator is not needed. Just use:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"title CONTAINS[c] %@", @"sh"];

If you want a more in depth explanation read: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Predicates/Predicates.pdf

In particular, pay attention to the section "Using Predicates with Key-Paths". Hopefully that helps.

like image 163
pbuchheit Avatar answered Oct 31 '22 04:10

pbuchheit