I am having a serious issue within my CoreData database. I have created a One To Many relationship between 2 tables and added a Fetched Property on the Table containing all unique values. All code works as expected within iOS 5 but in iOS 6 I receive the following errror:
2013-02-08 15:15:49.382 ArdsBoroughCouncil[16152:c07] * Terminating
app due to uncaught exception 'NSUnknownKeyException', reason:
'[<_NSObjectID_48_0 0xb25c3b0> valueForUndefinedKey:]: this class is
not key value coding-compliant for the key tour_id.'
* First throw call stack: (0x31c7012 0x24a3e7e 0x324ffb1 0x1c445ed 0x1bb08db 0x1bb088d 0x1bceb17 0x1bfe746 0x21b74bb 0x21b7176 0x21b6e44
0x21b66f4 0x21b2d63 0x21b2a82 0x21b2850 0x21b2625 0x21b1e07 0x21b18f4
0x21b0a6d 0x21ae9c9 0x2201276 0x227b155 0x2201071 0x2880014 0x286fd5f
0x286faa3 0x220103b 0x2200e9e 0x21ae9c9 0x2209dfa 0x22375cf 0x2237a03
0x59de1 0x11c2753 0x11c2a7b 0x11d0590 0x11d85bd 0x11d8eab 0x11d94a3
0x11d9098 0x1534da3 0x1526ad9 0x1526b54 0x24b7705 0x10e2920 0x10e28b8
0x11a3671 0x11a3bcf 0x11a2d38 0x111233f 0x1112552 0x10f03aa 0x10e1cf8
0x34b3df9 0x34b3ad0 0x313cbf5 0x313c962 0x316dbb6 0x316cf44 0x316ce1b
0x34b27e3 0x34b2668 0x10df65c 0x291d 0x2845) libc++abi.dylib:
terminate called throwing an exception
The predicate defined for the Fetched Property is:
($FETCH_SOURCE.tour_id == tour_id) AND ($FETCH_SOURCE != SELF)
I have defined the array to return all receive all values within my Tour class.
Are you aware of any issues with Fetched Properties wihtin iOS 6 ? As I cannot understand this works with no issue in iOS 5 but fails in iOS6.
Please see all other related code below:
The code below is how I am retrieving all records:
- (void)loadRecordsFromCoreData {
[self.managedObjectContext performBlockAndWait:^{
[self.managedObjectContext reset];
NSError *error = nil;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:NSStringFromClass([Tour class]) inManagedObjectContext:self.managedObjectContext];
[request setEntity:entityDescription];
[request setResultType:NSManagedObjectResultType];
[request setSortDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"tour_id" ascending:YES]]];
self.tours = [self.managedObjectContext executeFetchRequest:request error:&error];
}];
The code below shoes the NSManagedObjects I have defined:
-- Tour
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#class TourDetail;
#interface Tour : NSManagedObject
#property (nonatomic, retain) NSNumber * tour_id;
#property (nonatomic, retain) NSString * background_url;
#property (nonatomic, retain) NSString * summary;
#property (nonatomic, retain) NSString * title;
#property (nonatomic, retain) NSSet *tourdetails_tour;
#property (nonatomic, retain) NSArray *tourDetails;
#end
#interface Tour (CoreDataGeneratedAccessors)
- (void)addTourdetails_tourObject:(TourDetail *)value;
- (void)removeTourdetails_tourObject:(TourDetail *)value;
- (void)addTourdetails_tour:(NSSet *)values;
- (void)removeTourdetails_tour:(NSSet *)values;
#end
}
#import "Tour.h"
#import "TourDetail.h"
#implementation Tour
#dynamic tour_id;
#dynamic background_url;
#dynamic summary;
#dynamic title;
#dynamic tourdetails_tour;
#dynamic tourDetails;
#end
-- Tour Detail
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#class Tour;
#interface TourDetail : NSManagedObject
#property (nonatomic, retain) NSNumber * id;
#property (nonatomic, retain) NSNumber * tour_id;
#property (nonatomic, retain) NSNumber * lattitude;
#property (nonatomic, retain) NSNumber * longitude;
#property (nonatomic, retain) NSString * audiofile;
#property (nonatomic, retain) NSString * detail;
#property (nonatomic, retain) NSString * title;
#property (nonatomic, retain) Tour *tour_tourdetails;
#end
#import "TourDetail.h"
#import "Tour.h"
#implementation TourDetail
#dynamic id;
#dynamic tour_id;
#dynamic lattitude;
#dynamic longitude;
#dynamic audiofile;
#dynamic detail;
#dynamic title;
#dynamic tour_tourdetails;
#end
Any advise you can offer would be greatly appreciated :) As well as any examples you may have as to how best to define fetched properties ?
Thanks,
Michael
The code your using here is not clean
- (void)loadRecordsFromCoreData {
[self.managedObjectContext performBlockAndWait:^{
[self.managedObjectContext reset];
NSError *error = nil;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:NSStringFromClass([Tour class]) inManagedObjectContext:self.managedObjectContext];
[request setEntity:entityDescription];
[request setResultType:NSManagedObjectResultType];
[request setSortDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"tour_id" ascending:YES]]];
self.tours = [self.managedObjectContext executeFetchRequest:request error:&error];
}];
In fact, it is a little confusing.
Your calling a method, that calls a managed object context, which further calls itself within a synchronous block, which resets itself for no reason, which sets a property 'self.tours' outside of the block. All very odd. Can you explain why you are doing this?
Try this instead.
+(void)loadRecordsWithCompletion:(void(^)(NSArray *records, NSError *error))completion {
NSManagedObjectContext *context; //Your context
NSError *error;
NSSortDescriptor *sortDesc = [NSSortDescriptor sortDescriptorWithKey:#"attribute" ascending:YES];
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"EntityName"];
[request setSortDescriptors:#[sortDesc]];
NSArray *records = [context executeFetchRequest:request
error:&error];
completion(records, error);
}
Related
i new to core data. here i am trying to save bunch of Statement in one Month.But i dont know how to insert object in core data with relationship. what my code is doing, it saving month in Month entity and statements in Statement entity without any relationship. every time i save it create new object in Month entity. my DataModel has One to Many Relationships. for example current (month) November than i want to insert few statement related to November. than next month December i want to insert few statement related to December. thats what i am trying to achieve. sorry for bad my english.
`
NSManagedObjectContext *context = [self managedObjectContext];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Month" inManagedObjectContext:context];
Month *month = [[Month alloc] initWithEntity:entity insertIntoManagedObjectContext:context];
Statement *statement = [NSEntityDescription insertNewObjectForEntityForName:#"Statement" inManagedObjectContext:context];
statement.title = self.enterTextGreenViewTextField.text;
NSNumber *aNum = [NSNumber numberWithDouble:savingAmount];
statement.amount =aNum;
statement.isIncome = [NSNumber numberWithBool:isIncome];
[month addStatementsObject:statement];
NSError *error;
if (![context save:&error]) {
FATAL_CORE_DATA_ERROR(error);
return;
}
NSLog(#"savingStatement ****");
`
#import "Month.h"
NS_ASSUME_NONNULL_BEGIN
#interface Month (CoreDataProperties)
#property (nullable, nonatomic, retain) NSDate *monthOfStatement;
#property (nullable, nonatomic, retain) NSSet<Statement *> *statements;
#end
#interface Month (CoreDataGeneratedAccessors)
- (void)addStatementsObject:(Statement *)value;
- (void)removeStatementsObject:(Statement *)value;
- (void)addStatements:(NSSet<Statement *> *)values;
- (void)removeStatements:(NSSet<Statement *> *)values;
#end
NS_ASSUME_NONNULL_END
And
#import "Statement.h"
NS_ASSUME_NONNULL_BEGIN
#interface Statement (CoreDataProperties)
#property (nullable, nonatomic, retain) NSNumber *amount;
#property (nullable, nonatomic, retain) NSNumber *isIncome;
#property (nullable, nonatomic, retain) NSString *title;
#property (nullable, nonatomic, retain) Month *month;
#end
NS_ASSUME_NONNULL_END
Almost right, you have to create the two entities and then bind their relationship:
NSEntityDescription *month = [NSEntityDescription insertNewObjectForEntityForName:#"Month" inManagedObjectContext:[self managedObjectContext]];
Statement *statement = [NSEntityDescription insertNewObjectForEntityForName:#"Statement" inManagedObjectContext:context];
statement.title = self.enterTextGreenViewTextField.text;
NSNumber *aNum = [NSNumber numberWithDouble:savingAmount];
statement.amount =aNum;
statement.isIncome = [NSNumber numberWithBool:isIncome];
statement.month=month;
This line i don't know if manually generating the set is necessary, but I do it nonetheless:
NSMutableSet *monthStatements;
if(month.statements){
monthStatements=[NSMutableSet setWithSet:month.statements];
}else{
monthStatements=[NSMutableSet alloc] init];
}
[monthStatements addObject:statement];
month.statements = monthStatements;
Finally saving:
NSError *error=nil;
if (![context save:&error]) {
FATAL_CORE_DATA_ERROR(error);
return;
}
In my opinion this should work as charm (haven't tried it though) :-)
** Edit:
Fetching:
NSArray *fetchedObjects;
NSError *error=nil;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Store" inManagedObjectContext:[self managedObjectContext]];
[fetchRequest setEntity: entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat: #"code==%#", code];
[fetchRequest setPredicate:predicate];
fetchedObjects = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];
You typically will try to fetch the month in case it already exists, and if it doesn't you create it with the code I gave you. I don't know what you mean by creating new relationships though....
I have a coredata project with the following entities:
I'm trying to get the list of the content base on the category:
here is my coredata clasess .h:
#interface Content : NSManagedObject
#property (nonatomic, retain) NSString * contenido;
#property (nonatomic, retain) NSNumber * index;
#property (nonatomic, retain) NSString * titulo;
#property (nonatomic, retain) NSNumber * uploadCloudKit;
#property (nonatomic, retain) Categories *category;
---
#class Content;
#interface Categories : NSManagedObject
#property (nonatomic, retain) NSString * categoryName;
#property (nonatomic, retain) NSSet *content;
#end
NSEntityDescription *categoryDescription = [ NSEntityDescription entityForName:#"Categories" inManagedObjectContext:moc];
NSFetchRequest *categoRequest = [NSFetchRequest new];
categoRequest.entity = categoryDescription;
NSPredicate *categoPredicate = [NSPredicate predicateWithFormat:#"categoryName like %#", category];
categoRequest.predicate = categoPredicate;
NSArray *results = [moc executeFetchRequest:categoRequest error:&error];
but when I try to access the content on the result for the category I get:
po [results valueForKey:#"content"]
<__NSArrayI 0x6080000243a0>(
Relationship 'content' fault on managed object (0x6080000a2220) <Categories: 0x6080000a2220> (entity: Categories; id: 0x40002b <x-coredata://FDBA3FB2-F1F8-498E-9071-3A5D1ABE66F0/Categories/p1> ; data: {
categoryName = movies;
content = "<relationship fault: 0x610000030fa0 'content'>";
})
)
Any of you knows how can I get the content items of the result?
I'll really appreciate your help
It's a normal behaviour for CoreData. You should read Apple Documentation. There you can read about fault objects for CoreData. In two words - fault means that CoreData has this object but know (for some reason CoreData won't print you all fields of the object).
In order to see all vields you should do this:
[categoRequest setReturnsObjectsAsFaults:NO];
But I recomend you to do this only for debug, because CoreData smarter and know what to do with memory managment)
I am having Country, State and City entities in my CoreData model. Here is the structure:
#interface Country : NSManagedObject
#property (nonatomic, retain) NSString * cId;
#property (nonatomic, retain) NSString * title;
#property (nonatomic, retain) NSSet *states; // This will contain State object
#end
#interface State : NSManagedObject
#property (nonatomic, retain) NSString * sId;
#property (nonatomic, retain) NSString * title;
#property (nonatomic, retain) NSSet *cities; // This will contain City object
#property (nonatomic, retain) Country *country;
#end
#interface City : NSManagedObject
#property (nonatomic, retain) NSString * cityId;
#property (nonatomic, retain) NSString * title;
#property (nonatomic, retain) State *state;
#end
As you can see I have one to many relation between Country - State and State - City.
Now what I want is to fetch Country list with all states, but don't want city list associated with States.
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:#"Country"];
[request setPropertiesToFetch:#[#"cId", #"title", #"states"]];
NSError *error = nil;
NSArray *aryCategories = [gblAppDelegate.managedObjectContext executeFetchRequest:request error:&error];
setPropertiesToFetch Setting this property allows to have only mentioned fields from the entity but how to set only sid and title for NSSet states which contain State object.
For getting city list I will send another request.
Please help me on this.
You do not need propertiesToFetch. This feature (which BTW needs the NSDictionaryResultType) is for special situations where you have lots of data and only need certain fields. This is definitely not necessary in your case!
Just fetch the Country objects. Core Data will automatically optimize to avoid fetching unnecessary data into memory.
NSFetchRequest *request = [NSFetchRequest fetchRequestsWithEntityName:#"Country"];
// consider sorting
NSArray *countryList = [context executeFetchRequest:request error:nil];
You now have a country list. It contains also the states. To get the states of a particular country could not be simpler.
NSSet *states = country.states;
NB: I think calling your to-one relationship from City to State "country" is problematic. I suggest renaming it to state.
Need help in implementing delete rule in a core data relationship , I gone through all the article on the net but can't understand to implement the delete rule , does creating relationship takes cares of deletion process (which I doubt ) , I have creates the below entity with rule , but on deleting a entry in List_Main does not delete the entry in list_Item , I guess linking in not done (don't know how to do that )
I have two entity
Entity --------Relation Ship ---- Destination ---- Inverse ---- Properties ---- Delete Rule
List_main -- Main_to_Item ---- List_Item ----- Item_to_Main -- Optional -- Cascade
List_Item -- Item_to_Main ----- list_Main ------ Main_to_Item --- optional --- nullify
List_Main.h
#property (nonatomic, retain) NSString * list_Name;
#property (nonatomic, retain) NSDate * list_Reminder_Date;
#property (nonatomic, retain) NSNumber * list_Reminder_Flag;
#property (nonatomic, retain) NSSet *main_to_item;
#end
#interface List_Main (CoreDataGeneratedAccessors)
- (void)addMain_to_itemObject:(List_Item *)value;
- (void)removeMain_to_itemObject:(List_Item *)value;
- (void)addMain_to_item:(NSSet *)values;
- (void)removeMain_to_item:(NSSet *)values;
#end
List_Item.h
#interface List_Item : NSManagedObject
#property (nonatomic, retain) NSString * list_Items;
#property (nonatomic, retain) NSString * list_Name;
#property (nonatomic, retain) List_Main *item_to_main;
Now when in first view user enters the List Name in List_main
FirstView.m
NSManagedObjectContext *context = [self managedObjectContext];
NSManagedObject *newItem = [NSEntityDescription insertNewObjectForEntityForName:#"List_Main" inManagedObjectContext:context];
[newItem setValue:self.listName.text forKey:#"list_Name"];
NSDate *currentDate = [NSDate date];
currentDate = [self dateWithOutTime:currentDate];
[newItem setValue:currentDate forKey:#"list_Reminder_Date"];
[newItem setValue:NO forKey:#"list_Reminder_Flag"];
// Save
NSError *error = nil;
if (![context save:&error]) {
NSAssert(NO, #"Save should not fail");
[self showAlert];
}
After that the control goes to secondView to enter Item and makes entires in List_Item
secondView.m
NSManagedObject *category1 = [NSEntityDescription insertNewObjectForEntityForName:#"List_Item" inManagedObjectContext:self.context];
[category1 setValue:self.listName forKey:#"list_Name"];
[category1 setValue:combinedThumbNail forKey:#"list_Items"];
NSError *error = nil;
if (![self.context save:&error]) {
NSAssert(NO, #"Save should not fail");
[self showAlert];
}
and I have a delete command for respective entity
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
[context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];
Now how should I implement the delete rule using the relationship , really a showstopper for me :((
If you can point out any good tutorial that will also do
I am getting a EXC_BAC_ACCESS error when attempting to save a TRUE value into a managed object that contains a Boolean attribute.
id delegate = [[UIApplication sharedApplication] delegate];
self.managedObjectContext = [delegate managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"TrafficCameraInfo"
inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"code=%#",self.selectedTrafficCamera.code]];
NSError *error;
TrafficCameraInfo *cgTrafficCamera;
cgTrafficCamera = [[self.managedObjectContext executeFetchRequest:fetchRequest error:&error] lastObject];
NSString *alertMessage;
if (cgTrafficCamera.favourite == NO){
cgTrafficCamera.name = #"TEST"; <-- works ok
cgTrafficCamera.favourite = 1; <-- causes an error
} else {
cgTrafficCamera.favourite = 0;
}
error = nil;
if (![self.managedObjectContext save:&error]) {
The managed object interface looks like this:
#interface TrafficCameraInfo : NSManagedObject
#property (nonatomic, retain) NSString *code;
#property (nonatomic, retain) NSString *postCode;
#property (nonatomic, retain) NSNumber *latitude;
#property (nonatomic, retain) NSNumber *longitude;
#property (nonatomic, retain) NSString *name;
#property (nonatomic, retain) NSString *url;
#property (nonatomic) Boolean favourite;
#end
Elsewhere in my app i am updating another Boolean field by passing a 1 to it and am not encountering a problem.
Any ideas what is causing the error?
I think in your core data attribute table you define "favorite" variable to BOOL,well that means it's an NSNumber Type,so you should set the data using NSNumber
A Boolean is a simple, scalar, non-pointer datatype. Core Data properties are always stored as objects. The Objective-C object wrapper for numeric datatypes is NSNumber. So if favourite is a regular stored property, you should declare it as:
#property (nonatomic, retain) NSNumber *favourite;
Assignment would be done like this:
cgTrafficCamera.favourite = [NSNumber numberWithBool:YES]; // Obj-C style is "YES/NO" for BOOL
Or this if you prefer:
cgTrafficCamera.favourite = [NSNumber numberWithBool:1];
If you don't need to store the Boolean, you can leave it as such and make it a transient property. You'll probably need to get rid of the "(nonatomic)" in that case.