views:

79

answers:

4

The following is implemented as a class method in a category on one of my managed object entities, with a bunch of other operations:

+ (NSArray*)newArrayOfAllOtherBibs
{
  NSManagedObjectContext* moc = [(MyAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
  NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init];    
  NSString* entityName = NSStringFromClass([self class]);

  NSEntityDescription* entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:moc];
  [fetchRequest setEntity:entity];

  NSError* error;
  NSArray* items = [moc executeFetchRequest:fetchRequest error:&error];
  [fetchRequest release];

  NSMutableArray* bibArray = [NSMutableArray array];

  for(int i = 0; i < [items count]; i++)
  {
    Person* person = [items objectAtIndex:i];

    if(![person.isSelf isEqualToString:@"YES"])
    {
// crash here!
      if([person.bib length] > 0)
// crash here!
        [bibArray addObject:person.bib];
    }
  }
  return [bibArray retain];
}

So it is supposed to look at all entities for Person, returned for a very simple fetch, and add all that are not marked as "self" (attribute isSelf, type NSString) to a new array which is returned to the caller. All the other methods for add/delete/find matching are working well.

Using

NSString* entityName = NSStringFromClass([self class]);

is an attempt to make the function more generic so I can cut&paste these functions for other entities as required with less editing.

Person looks like this:

    @interface Person :  NSManagedObject  
    {
    }

    @property (nonatomic, retain) NSString * bib;
    @property (nonatomic, retain) NSString * isSelf;
[...]    
    @end

Question is, what could explain EXC_BAD_ACCESS on the line marked? Analyzer shows nothing. At that point person is clearly OK or I would expect it to die earlier, on accessing .isSelf. (It could be made a boolean but I find having two kinds of boolean, one BOOL and one NSNumber, error prone). If person.bib is nil then calling length on it should still return 0 right? But it can't be nil anyway since "bib" is the key for these entities and one is never created without it. At this stage nothing has been deleted from the store, it's a fresh store that has been saved since last addition.

A: 

The best thing to do is set NSZombieEnabled in the executable and debug it from there. This way you'll be able to see what is causing the problem.

Liam
That's a very good method for finding where your problem is - but I've narrowed it down and the issue is one of "how can this be" rather than "why am I crashing"? Receiving a Core Data object with a primary key (marked non-optional) that is nil is very surprising.
Adam Eberbach
A: 

If you are loading some vars lazily make sure you set them to nil when you release them because if not next time when accessed them. They will not be "skipped", you app will try to use them but since they are not pointing to a valid object it fails and gives you errors like EXC_BAD_ACCESS

nacho4d
Not really - I only ever use the Person entity right after doing a fetch as shown. They can be deleted using [managedObjectContext deleteObject:person]; but never in the same method.
Adam Eberbach
A: 

Person.bib may not have been loaded yet.

Did you leave the bib property defined as @dynamic and not @synthesize?

Did you override the bib accessor method? If so your override needs to be KVO friendly.

Graham Perks
I haven't touched the Xcode-generated files.
Adam Eberbach
A: 

The cause of the problem:

  NSDictionary *resultDict = [responseString JSONValue];
    NSString* bib = [resultDict objectForKey:@"bib"];
      person = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:moc];
      person.bib = bib;

[... lots of stuff setting up relationships for person etc.]

  NSError *error;
  if (![moc save:&error]) 
  {
    NSLog(@"Core Data Save error %@, %@", error, [error userInfo]);
  }

The fix:

person.bib = [bib copy];

seems like the bib string was not valid at the time the Person entity was saved.

Adam Eberbach