I want to read some data from Core Data for statistics. My datamodel is like in the tutorials found in the internet (a bit of clicking and voilĂ it is ready). But now I want to work with the data.
My function:
-(int)calcAve {
int ret=0;
ret = [[stats valueForKey:#"aveScore"] intValue];
NSLog(#"%d",ret);
return ret;
}
stats is the object connected from the .xib to the class, which. This object is bound to the entity Stats in the datamodel. [stats entity] returns the correct value.
aveScore is one object in the entity stats (no misspelling, checked it multiple times!). No the error shows me, that stats is not the correct datamodel:
this class is not key value coding-compliant for the key
What is wrong with this? Is there a simple way to read out the data from Core Data?
I am not sure what you managedObject in this case is. However usually you want to store more than one managedObject of the same class in a managedObjectContext. For example several recipes objects in a MOC. Every recipe has the properties.
Your call for value for key sounds reasonable. Check what that class of the stats object is. If it is not of the class NSManagedObject or your custom subclass of it you have a problem. You can only store NSManagedObjects within CoreData. You can check it like this:
NSString *className = NSStringFromClass([stats class]);
NSLog(#"class name: %#",className);
The way you are asking I suggest you try to read the CoreData docs again and look at the Recipes example in Apple's sample code library.
Related
I'm a nwebie in Core Data, i have designed a navigation based application and some of the data i use are created on run time(come from a URL via JSON). I took a few tutorials an searched for almost a day but haven't still realized how to save the incoming JSON data to the Entity (or event?) in my Core Data model. I fetch the data in the DetailViewController class and i need to save this data to Core Data(I have prepared an Entity with 7 properties). Can anyone please help?(If you know a good tutorial or sample code i will be pleased)
EDIT This may be a little specific but i really have trouble with and need just a little help.
My data comes to the app from a kind of restful server(i wrote it in PHP), firstly user enters his/her login informations(which i have saved to the database on server before) and when the response data comes i will use different elements of it in differen views(for example the user_id will be used on a view and the buttonData etc on other views). My question is, how will i save JSON data into my core data model(has tree Entities for the moment). Thanks in advance
Note: I lokked arround a lot but couldn't find any answer&tutorial about an app like mine
The best way to do that would be to create entities corresponding to JSON structure. Easiest was is when each JSON object becomes an entity, and arrays become arrays of entities. Be reasonable, however, and don't introduce too much overkill for JSON subobjects that are essentially part of its superobject.
When you have created entities, you can start off with the parsing and translation. Use some JSON framework (starting from iOS5 there's one from Apple) and parse JSON string into object tree, where root item is either an NSArray or NSDictionary, and subelements will be NSArray, NSDictionary, NSNumber, NSString or NSNull.
Go over them one by one in iterational loops and assign according values to your core data entity attributes. You can make use of NSKeyValueCoding here and avoid too much manual mapping of the attribute names. If your JSON attributes are of the same name as entity attributes, you'll be able to just go over all dictionary elements and parse them into attributes of the same name.
Example
My parsing code in the similar situation was as follows:
NSDictionary *parsedFeed = /* your way to get a dictionary */;
for (NSString *key in parsedFeed) {
id value = [parsedFeed objectForKey:key];
// Don't assign NSNull, it will break assignments to NSString, etc.
if (value && [value isKindOfClass:[NSNull class]])
value = nil;
#try {
[yourCreatedEntity setValue:value forKey:property];
} #catch (NSException *exception) {
// Exception means such attribute is not defined in the class or some other error.
}
}
This code will work in trivial situation, however, it may need to be expanded, depending on your needs:
With some kinds of custom mappings in case you want your JSON value be placed in differently named attribute.
If your JSON has sub-objects or arrays of sub-objects, you will need to detect those cases, for example in setters, and initiate new parsing one level deeper. Otherwise with my example you will face the situation that assigns NSDictionary object to an NSManagedObject.
I don't think it is reasonable to dive into these, more advanced matters in scope of this answer, as it will expand it too much.
I suggest you to use this library : https://github.com/TouchCode/TouchJSON
And then if you want to make a factory to parse json and feed your code data, you can use selectors to call methods to fill all your attributes.
Chances are your JSON data gets converted to an NSDictionary or NSArray (or some combination of the two). Simply extract the key/values from the JSON structure and add them to your entity class.
This lib helps me lot
Features
Attribute and relationship mapping to JSON key paths.
Value transformation using named NSValueTransformer objects.
Object graph preservation.
Support for entity inheritance
Works vice-versa
In many uses of data one thing confuses me. EG in CoreData and the NSManagedObject subclass's property names are the same as the properties in the CoreData attributes. Similar things go on with the NSXMLParser.
Why is this? it's confusing to me because I never see the string for the name of attribute being used. While NSLoging a fetch request object I get,
"<Person: 0x6d5be20> (entity: Person; id: 0x6d5dce0 <x-coredata://6800B6A5-87AF-46B4-9836-9D412A9B3EE4/Person/p1> ; data: {\n age = 51;\n firstName = Anthony;\n lastName = Robbins;\n})",
As one of the array elements. I wouldn't expect any different.
But in the tutorial when I itterate through the array using
for (Person *thisPerson in persons)
(thisPerson being the data object with the mysterious properties). The property names seem to have been sorted according to name.
NSLog(#"First Name = %#", thisPerson.firstName);
Why the hell is this? Surely a barrage of NSRegex expressions and string modifications would be required to extrapolate this data.
As for Core Data (not NSXMLParser) Core Data simply uses the property name to look up the corresponding property in the model. If you're accessing lastName on an NSManagedObject instance with foo.lastName there should be no implementation for
-(NSString *)lastName
This will cause the NSObject class to fall back to NSKeyValueCoding which will turn that call into
[foo valueForKey:#"lastName"]
The NSManagedObject class overrides -valueForKey: (and other NSKeyValueCoding relating methods) and uses that to access data through the NSPersistentStoreCoordinator.
I'm a nwebie in Core Data, i have designed a navigation based application and some of the data i use are created on run time(come from a URL via JSON). I took a few tutorials an searched for almost a day but haven't still realized how to save the incoming JSON data to the Entity (or event?) in my Core Data model. I fetch the data in the DetailViewController class and i need to save this data to Core Data(I have prepared an Entity with 7 properties). Can anyone please help?(If you know a good tutorial or sample code i will be pleased)
EDIT This may be a little specific but i really have trouble with and need just a little help.
My data comes to the app from a kind of restful server(i wrote it in PHP), firstly user enters his/her login informations(which i have saved to the database on server before) and when the response data comes i will use different elements of it in differen views(for example the user_id will be used on a view and the buttonData etc on other views). My question is, how will i save JSON data into my core data model(has tree Entities for the moment). Thanks in advance
Note: I lokked arround a lot but couldn't find any answer&tutorial about an app like mine
The best way to do that would be to create entities corresponding to JSON structure. Easiest was is when each JSON object becomes an entity, and arrays become arrays of entities. Be reasonable, however, and don't introduce too much overkill for JSON subobjects that are essentially part of its superobject.
When you have created entities, you can start off with the parsing and translation. Use some JSON framework (starting from iOS5 there's one from Apple) and parse JSON string into object tree, where root item is either an NSArray or NSDictionary, and subelements will be NSArray, NSDictionary, NSNumber, NSString or NSNull.
Go over them one by one in iterational loops and assign according values to your core data entity attributes. You can make use of NSKeyValueCoding here and avoid too much manual mapping of the attribute names. If your JSON attributes are of the same name as entity attributes, you'll be able to just go over all dictionary elements and parse them into attributes of the same name.
Example
My parsing code in the similar situation was as follows:
NSDictionary *parsedFeed = /* your way to get a dictionary */;
for (NSString *key in parsedFeed) {
id value = [parsedFeed objectForKey:key];
// Don't assign NSNull, it will break assignments to NSString, etc.
if (value && [value isKindOfClass:[NSNull class]])
value = nil;
#try {
[yourCreatedEntity setValue:value forKey:property];
} #catch (NSException *exception) {
// Exception means such attribute is not defined in the class or some other error.
}
}
This code will work in trivial situation, however, it may need to be expanded, depending on your needs:
With some kinds of custom mappings in case you want your JSON value be placed in differently named attribute.
If your JSON has sub-objects or arrays of sub-objects, you will need to detect those cases, for example in setters, and initiate new parsing one level deeper. Otherwise with my example you will face the situation that assigns NSDictionary object to an NSManagedObject.
I don't think it is reasonable to dive into these, more advanced matters in scope of this answer, as it will expand it too much.
I suggest you to use this library : https://github.com/TouchCode/TouchJSON
And then if you want to make a factory to parse json and feed your code data, you can use selectors to call methods to fill all your attributes.
Chances are your JSON data gets converted to an NSDictionary or NSArray (or some combination of the two). Simply extract the key/values from the JSON structure and add them to your entity class.
This lib helps me lot
Features
Attribute and relationship mapping to JSON key paths.
Value transformation using named NSValueTransformer objects.
Object graph preservation.
Support for entity inheritance
Works vice-versa
I have an xcdatamodel with a set of entities built in a static library.
I am including this static library in a project. I would like to create another model in main project, with entity named Task. I would like to have an attribute in the entity where I could store the NSManagedObjectID of an entity created in static library. With NSManagedObjectID I could easily fetch the main store and get the entity.
In the end there could be many Task entities refer to an objectID.
Is it possible ? I also understand that this is sounds like a relational model, which Core Data isn't, so is there a better solution for dealing with the subject?
thanks
The NSManagedObjectID is in itself not coding compliant. But you can get the URL representation of an object ID and store that. Like this:
myObject.externalTaskURL = [[task objectID] URIRepresentation];
Then in order to get the object ID back to retrieve the task object it refers to later (psc is your NSPersistentStoreCoordinator where the Task entities live):
NSManagedObjectID* taskID =
[psc managedObjectIDForURIRepresentation:myObject.externalTaskURL];
Make sure to never do this to a temporary managed object ID.
You can store a managed object ID as a NSURL in a transformable attribute.
I was wondering if anyone can point me in the direction of how to set up auto increment on an attribute in a coredata entity. I know the indexed check box just makes the field indexed for searching and lookup speeds.
I also know that I will have to do this in code, but I'm not sure on how to get the last/highest ID to set the new objects ID. I found how to do this years ago but can't find it again.
I have a very limited knowledge of Objective-C and even more so of coredata. Also if someone could suggest how to make sure that a field is unique, such as the name field as well that would be great.
My code is here if you want to have a look at what I have done so far. The project is a basic database that contains parts and there locations and also tools. It's only partly finished, basically a small database for my person electronics kit. I'm sure there are apps that will do this but its always better when you make it your self
I'm not quite sure what the id does in your app, but my first observation is that all the entities in your data model have both a name and an id, so they should probably have an abstract super-entity to contain name and id. Other than that, you can retrieve the max id in a set like this:
Category *cat = /* get a category */;
NSSet *parts = cat.parts;
NSNumber *maxID = [parts valueForKeyPath:#"#max.id"];
for the id's of a category you could perform a fetch request for all the categories and then use this technique on the array that is returned. I don't know if you want to keep the id's of each model object unique or you want id's to start with 0 for the first object added to each entity.
To make sure a field is unique you can use managed object validation. this is described in the Core Data Programming Guide and in more detail in the Model Object Implementation Guide. Making sure that a name is unique would require you to test it against all the names in a validateName:error: method. making an abstract super entity will make this a lot easier. To do it you get all the names of objects in the abstract super entity and test them against the value to be validated.
Edit: If you use the abstract super entity then you should get the max id of the objects in the abstract super entity if you want them to be unique. Also as someone else pointed out the objectID of a managed object is a unique identifier for it that will always be the same, but looking at the app I don't think that's really what you want, because they will be computer numbers rather than the friendlier results of incrementing the highest known id when a new object is created. Another thing you should set the objet id in awakeFromInsert so that it is only called when the object is created.
this is how apple implemented autoincrement:
- (void) awakeFromInsert
{
[super awakeFromInsert];
static int tempID = 0;
[self setValue:[NSNumber numberWithInt:++tempID] forKey:#"id"];
}