0

I am trying to implement Core Data in an iOS 7 app (and have successfully done so earlier). However, when I execute the executeFetchRequest method, the app crashes. The most relevant code is added below:

#import "JTHuntingSeasonDB.h"

@implementation JTHuntingSeasonDB

- (id)init {
    self = [super init];
    if (self) {
        NSFileManager *fileManager = [NSFileManager defaultManager];
        NSURL *documentsDirectory = [[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] firstObject];

        NSString *documentName = @"JTHuntingDB";
        NSURL *url = [documentsDirectory URLByAppendingPathComponent:documentName];

        document = [[UIManagedDocument alloc] initWithFileURL:url];


        BOOL fileExists  = [[NSFileManager defaultManager] fileExistsAtPath:[url path]];

        if (fileExists) {
            [document openWithCompletionHandler:^(BOOL success) {
                if (success) {
                    NSLog(@"Document opened successfully");
                    self.allSpecies = [self getSpecies];
                    self.speciesToday = [self getSpeciesToday];
                } else NSLog(@"Failed to open document");
            }];
        } else {
            [document saveToURL:url forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
                if (success)  {
                    NSLog(@"Document created successfully");
                    self.allSpecies = [self getSpecies];
                    self.speciesToday = [self getSpeciesToday];
                }  else NSLog(@"Failed to create document, path: %@", url);
            }];
        }
    }

    return self;
}

#pragma mark - Core Data

- (NSArray *)getSpecies {
    if (document.documentState == UIDocumentStateNormal) {
        context = document.managedObjectContext;

        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        NSString *country = [defaults stringForKey:@"Country"];
        NSString *subregion = [defaults stringForKey:@"Subregion"];

        NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"HuntingDates"];
        NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES selector:@selector(localizedStandardCompare:)];
        request.fetchBatchSize = 150;
        request.fetchLimit = 150;
        request.sortDescriptors = @[sortDescriptor];

        if (subregion.length > 0) {
            request.predicate = [NSPredicate predicateWithFormat:@"(country IN %@) AND (subregion IN %@)", country, subregion];
        } else {
            request.predicate = [NSPredicate predicateWithFormat:@"country IN %@", country];
        }

        NSError *error;
        return [context executeFetchRequest:request error:&error];
    }

    return nil;
}

The line

return [context executeFetchRequest:request error:&error];

causes the app to crash. This is what I have done and discovered so far:

  • Simulator: Deleted app and reset content and settings
  • Xcode: Clean (Build folder)
  • "context" is not nil
  • NSLog prints out "Document created/opened successfully"
  • Only "lldb" is printed in the console when the app crashes

Edit: After following Wain's advice, I turned exception breakpoint off, got a more descriptive error message saying that the predicate was invalid. Problem solved by replacing IN in the predicate with CONTAINS and also changing the variable "country" so that it did not return nil anymore.

Jorn
  • 1,054
  • 9
  • 25
  • 1
    Did you try continuing when the exception was hit to try to get a stack trace? – Wain Jan 31 '14 at 22:46
  • I don't know core data but would at least look that request contains what you expect it to. – Gruntcakes Jan 31 '14 at 22:47
  • Apart from Len there must be more in the console and in the debugger backtrace. Without that it is hard to help. – Volker Jan 31 '14 at 23:26

2 Answers2

1

I guess it's your predicates, because IN is a collection operator but you're passing strings (should be array / set).

If you're using strings, you should be using CONTAINS in the predicate.

Wain
  • 118,658
  • 15
  • 128
  • 151
  • Thanks. Removing the exception breakpoint as you suggested in the comment above, revealed that the predicate was invalid. I replaced IN with CONTAINS, but I also discovered that the variable used in the predicate (country) was nil, causing the crash. – Jorn Feb 01 '14 at 09:53
0

Assuming the CoreData persistent store lives inside the document, you will want to use a UIManagedDocument