Reputation: 565
I have one to many mapping relation with name match and innings.
match <-->> innings
match
has fields name, id etc.innings
has fields number.I am able to get match
properties. I create a new match in MatchList
in TableListController
. I see the data for Match
and innings
is available in the table. Now, I click the row that was created in the table.
But when I do [match matchinnings],
I get a NSSet* inningSet
. I am able to get two objects inningA and inningB from inningSet. When I try call [inningA number]
, I get an error.
Below is my NSFetchResultsController method:
- (NSFetchedResultsController *)fetchedResultsController {
// Set up the fetched results controller if needed.
//NSLog(@"Inside fetchResultsController ");
if (fetchedResultsController == nil) {
// Create the fetch request for the entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setReturnsObjectsAsFaults:NO];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Match" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setRelationshipKeyPathsForPrefetching:[NSArray arrayWithObject:@"matchinnings"]];
[fetchRequest setIncludesSubentities:YES];
[fetchRequest setResultType:NSManagedObjectResultType];
//[fetchRequest setPropertiesToFetch:[NSArray arrayWithObjects:@"matchinnings.number", nil]];
//[fetchRequest valueForKeyPath:@"matchinnings.number"];
//[fetchRequest setPropertiesToFetch:[NSArray arrayWithObjects:@"matchinnings", @"number", nil]];
//[fetchRequest setRelationshipKeyPathsForPrefetching:[NSArray arrayWithObject:@"matchinnings.number"]];
//[fetchRequest setRelationshipKeyPathsForPrefetching:[NSArray arrayWithObjects:@"matchinnings", @"matchinnings.number", nil]];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:@"Root"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor release];
[sortDescriptors release];
}
return fetchedResultsController;
}
In my class MatchContextMO, I get a I get error a EXC_BAD_ACCESS
on the line:
inningsArray = [newSet allObjects];
...in this method:
-(NSArray *)determineInningsOrder {
NSArray* array = nil;
NSSet *newSet = [self.match valueForKey:@"matchinnings"];
NSLog(@"Size of set %d", [newSet count]);
NSArray *inningsArray = nil;
@try {
inningsArray = [newSet allObjects];
}
@catch (NSException *exception) {
NSLog(@"Exception in matchinnings %@", [exception reason]);
}
Innings *inningA = [inningsArray objectAtIndex:0];
Innings *inningB = [inningsArray objectAtIndex:1];
if ([inningA isKindOfClass:Innings.class])
NSLog(@"inningA is of type Innings");
Innings* temp;
NSNumber *numberA = [inningA valueForKey:@"number"];
NSLog(@"numberA %d", [numberA intValue]);
if ([numberA intValue] == 2) {
temp = inningA;
inningA = inningB;
inningB = temp;
}
array = [NSArray arrayWithObjects:inningA, inningB, nil];
return array;
}
I am trying to figure it out for last one week. It looks more like CoreData faults.
Your help is greatly appreciated.
I tried iterating over the set returned. Still got a 'EXC_BAD_ACCESS' error on line [a addObject:inningsObject]
. NSLog size of set says 2 though.
-(NSArray *)determineInningsOrder {
NSArray* array = nil;
if (!self.match) {
NSLog(@"Match is null");
return nil;
}
NSMutableSet *newSet = [self.match valueForKey:@"matchinnings"];
NSLog(@"Size of set %d", [newSet count]);
//NSSet *inningsSet = [self.match matchinnings];
NSArray *inningsArray = nil;
NSEnumerator *fastEnumerator = [newSet objectEnumerator];
id inningsObject;
NSMutableArray *a = [[NSMutableArray alloc] initWithCapacity:[newSet count]];
while ((inningsObject = [fastEnumerator nextObject])) {
[a addObject:inningsObject];
}
Innings *inningA = [a objectAtIndex:0];
Innings *inningB = [a objectAtIndex:1];
[a release];
if ([inningA isKindOfClass:Innings.class])
NSLog(@"inningA is of type Innings");
NSNumber *numberA = [inningA valueForKey:@"number"];
NSLog(@"numberA %d", [numberA intValue]);
if ([numberA intValue] == 2) {
temp = inningA;
inningA = inningB;
inningB = temp;
}
array = [NSArray arrayWithObjects:inningA, inningB, nil];
return array;
}
Upvotes: 1
Views: 2863
Reputation: 34983
I'm having the same issue, EXC_BAD_ACCESS
when I access a one-to-many relationship's count
when the containing objects are in a Fault state.
myObject.oneToManyRelationshipProperty.count; <- EXC_BAD_ACCESS
This seems to be fixed by setting relationshipKeyPathsForPrefetching
during the Fetch Request, which will "pre-load" the relationship objects during the initial fetch and not fault.
NSFetchRequest *fetchRequest = ...
fetchRequest.relationshipKeyPathsForPrefetching = @[@"yourProperty"];
Feedback on this solution appreciated. I don't understand why I'm getting the bad access; shouldn't access of a Fault simply load the object (and not crash)?
Upvotes: 0
Reputation: 4232
It's a bad idea to give properties names like "number" or "text" or "description", unless you are deliberately subclassing. Core Data actually gives a warning when you try the last, but it doesn't do so with all reserved words. From the NSPropertyDescription Class Reference:
Note that a property name cannot be the same as any no-parameter method name of NSObject or NSManagedObject. For example, you cannot give a property the name "description". There are hundreds of methods on NSObject which may conflict with property names—and this list can grow without warning from frameworks or other libraries. You should avoid very general words (like "font”, and “color”) and words or phrases which overlap with Cocoa paradigms (such as “isEditing” and “objectSpecifier”).
Using valueForKey:
consistently, most of the time circumnavigates this problem, but as soon as you make a call like [inningA number]
, you get an error.
Upvotes: 0
Reputation: 129
It's a little difficult to tell without some more of your implementation, but I would take a look at:
Upvotes: 0
Reputation: 1832
You are using a cache. This comes with all sorts of issues. I have read the docs many many times and I'm still not sure when it's refreshed. Try changing the cache to nil. It may be that one of the objects in the cache is no longer in the store and it's trying to access it.
Also get rid of these lines. They are not useful at this stage, and by the looks of your program won't be useful:
[fetchRequest setRelationshipKeyPathsForPrefetching:[NSArray arrayWithObject:@"matchinnings"]];
[fetchRequest setIncludesSubentities:YES];
[fetchRequest setResultType:NSManagedObjectResultType];
Where is the managedObjectContext created? Is it in the same thread that you are running this code? Does it still have a retain count? Try NSLog(@"MOC Retain count: %i", [managedObjectContext retainCount]);
If it's not in the same thread make sure that it is. It's not thread safe and you will get these errors if it's not.
How are you setting match? It's not clear from your code. The NSFetchedResultsController is useful for populating a table view, yet match is a property. How is it set? Is NSFetchedResultsController the correct interface to use? Would a normal fetch work as well?
If none of these work I think it's best that you post the contents of the entire file here. As others have said, what's there is right, and it is very hard to diagnose something that we can't see.
Upvotes: 0
Reputation: 64428
If matchinnings
key is the name for a to-many relationship then then:
[self.match valueForKey:@"matchinnings"];
... will return not an NSSet but an NSMutableSet. When you assign it to a NSSet like so:
NSSet *newSet = [self.match valueForKey:@"matchinnings"];
it can lead to problems if you forget and try to change anything.
However, in this case, that is probably not the issue. More likely, you are not getting a set returned at all. I would confirm you are getting a NSMutableSet returned.
I can tell you will absolute certainty that this problem is not being caused by faults. Firstly, you explicitly don't fetch as faults and secondly it is impossible for a fault to cause this kind of problem. Whenever an attribute of a fault represent object is accessed, the full object is read-in (faulted-in in the jargon.) Faults never trigger issues related to attribute access.
Upvotes: 0
Reputation: 8357
Of course if you model something in CoreData as an Integer
and provide a custom class to implement it. The attribute is an object: NSNumber
.
Example:
.h:
// attributes
@property (nonatomic, retain) NSNumber *version;
// derived attributes
@property (nonatomic, readonly) NSInteger versionIntegerValue;
@property (nonatomic, readonly) NSString *versionStringValue;
.m:
@dynamic version;
- (NSInteger)versionIntegerValue {
return [self.version integerValue];
}
- (NSString *)versionStringValue {
return [NSString stringWithFormat:@"v%d", [self.version integerValue]];
}
Upvotes: 1
Reputation: 1832
What is the object type of inningA or inningB? Ensure that:
If those are all correct, please reformat your question so we can read it easier.
Also be more clear as to where you are calling the bottom function? And provide the rest of MatchContectMO. I'm not sure what it is? Is it the MO definition? Or is there something that contains an MO? (The name is not at all clear).
Upvotes: 0