After the following of a tutorial I looked where the value and the corrosponding 'key' was set.
[aBook setValue:currentElementValue forKey:elementName];
My one problem with this is that this method is for dictionaries, not NSArrays.
The setValue:forKey: method applies to everything that supports Key Value Coding. It lets you set a value for a property identified by a string. In this particular case, the string comes from the name of the XML element the parser has finished processing, and the value comes from the text of the corresponding element.
The KVC trick lets you use the XML parser to set values of objects without hardcoding the names of objects' properties or methods. For example, if you have a fragment of XML like this
<book>
<author>Kernighan and Ritchie</author>
<title>The C Programming Language</title>
</book>
and a KVC-compliant Book class with NSString* properties author and title, the parser would be able to process the XML and set values of the properties without knowing anything about the structure of your XML or the structure of your Book class.
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
I'm relatively new to Objective-C (mainly using cocoa/apple foundation framework), but a long-time C++ programmer, so I'll start by explaining what I'm trying to accomplish; It's quite possible my approach isn't the best one, so I'd love to hear any suggestions for a different approach.
I've got a text file in json format, just made this quick example:
"section1" : {
"director" : "Sample Name 1",
"writers" : {
"name" : "Example Name 1",
"name" : "Example Name 2",
},
},
And I've got a class with properties which I want to match with the data inside this file, since I'm planning to parse this file and store some of the values in an instance of this class. My class header would look roughly like this:
#interface SongData : NSObject
#property (nonatomic, copy) NSString *director;
#property (nonatomic, copy) NSArray *writers;
#end
So I'm trying to find the cleanest, somewhat "data-driven" way to store this json data into the correct properties. Basically I want a way to loop through the json "dictionary" of data, and somehow use the "keys" to match with the correct property in my class and assign the value to that property. My first crack at it, I created a dictionary where the "key" is the actual key to lookup the proper data inside the json data, and the "value" would be a pointer to the correct class property. Sort of like this:
NSDictionary *descriptionDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:
director, #"name",
writers, #"writers",
nil];
Then the idea was to loop through the json data (which is stored in another NSDictionary), use each key from my "descriptionDictionary" to lookup the appropriate value in the json data, then use the matching "value" of the description dictionary based on the same key (which I was hoping is sort of a pointer to the actual class property?) and set that properties value to the value from the json data. Perhaps an example will make it a bit more clear :-). Lets assume "jsonDictionary" is the result of parsing my json data, and I'm already inside section1, so there should be a 1-1 match between keys that make up the jsonData NSDictionary and the keys that make up my descriptionDictionary NSDictionary:
[descriptionDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {
value = [jsonDictionary objectForKey:propertyName];
}];
Now "value" would technically be pointing to one of my classes properties, and I want to assign relevant json data to it (ie director = #"Sample Name 1"). I know there's problems with what I'm doing (I realize that I probably can't just dereference a pointer to a random class property and assign an arbitrary object of unknown type to it, hoping it all matches up :-) but hoping my example at least illustrates what I'm trying to do so someone can tell me a better way.
Have a look at KVC (source: http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/KeyValueCoding/Articles/BasicPrinciples.html)
Setting Attribute Values Using Key-Value Coding
The method setValue:forKey: sets the value of the specified key,
relative to the receiver, to the provided value. The default
implementation of setValue:forKey: automatically unwraps NSValue
objects that represent scalars and structs and assigns them to the
property. See “Scalar and Structure Support” for details on the
wrapping and unwrapping semantics.
If the specified key does not exist, the receiver is sent a
setValue:forUndefinedKey: message. The default implementation of
setValue:forUndefinedKey: raises an NSUndefinedKeyException; however,
subclasses can override this method to handle the request in a custom
manner.
The method setValue:forKeyPath: behaves in a similar fashion, but it
is able to handle a key path as well as a single key.
Finally, setValuesForKeysWithDictionary: sets the properties of the
receiver with the values in the specified dictionary, using the
dictionary keys to identify the properties. The default implementation
invokes setValue:forKey: for each key-value pair, substituting nil for
NSNull objects as required.
One additional issue that you should consider is what happens when an
attempt is made to set a non-object property to a nil value. In this
case, the receiver sends itself a setNilValueForKey: message. The
default implementation of setNilValueForKey: raises an
NSInvalidArgumentException. Your application can override this method
to substitute a default value or a marker value, and then invoke
setValue:forKey: with the new value.
As long as your class properties have the same names as the JSON fields you can use the setValuesForKeysWithDictionary: and pass in the JSON root dictionary.
For keys/properties that are named differently you can simply override the setValue:forUndefinedKey: and set the appropriate property yourself.
Finally there is the case of a value being represented by a different type in the JSON than in the property. For example NSURL would be an NSString instead. Here you can simply check the class of the passed parameter and if it does not match the IVAR, do a conversion.
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
Hello to all in this lovely community,
I am trying to get the contents of the data that is returned with a SudzC method from my web service. The webservice sends the data in a kind of partial XML like this:
<gUser>
<user USERID="224" USERNAME="name" USERSURNAME="surname" PASSWORD="123" TELEPHONE="+123" EMAIL="" USERTYPE="2"></user>
</gUser>
This is returned as (id) in the SudzC method. It can be assigned to a dictionary, string and it can be printed with NSLog etc. However, I was not able to get what I need; the attributes of USERID, USERNAME and so on.
EDIT
The result is of type NSCFString. It contains the whole XML data I wrote above in one string object. I tried to call a parser method that takes an NSString* obj(in this case, the result) as parameter, it gives the unrecognized selector exception. How am I going to parse/use this data if I can't divide the whole into pieces.
How should I proceed? Any help is much appreciated.
Regards,
Besel
According to the documentation for sudzc each element returned has a method called -attributes that contains all of that element's attributes as an array of nodes. You'll then have to iterate through that array to find the attributes you want.
I have a table column that I'm binding to a value in an NSArrayController. What I'm trying to do is display only a substring of the actual value in the array controller. The way I've been trying to do that so far is by creating an NSValueTransformer subclass, and then doing the string manipulation in the transformedValue method. However, I can't figure out how to get the incoming value turned into a string (it's of type NSConcreteValue), and maybe there's an easier way to do this without value transformers.
Sounds like you're doing presentation-side formatting, in which case you should be using a formatter instead.
Then again, if this is a string containing multiple values (e.g., something like “from 42 to 100”), you should make a model object from it instead, and store those in the array controller. Then you can bind your table columns to specific properties of the model objects, and not have to worry about picking the string apart and then reassembling it (except when you load and later save the model).
Edit: Never mind; I didn't see that the object values are NSValues, not NSStrings.
You can get a string representation of any object using the -description method, but for instances of NSValue it's unlikely to print anything especially meaningful. In other words, it's up to your value transformer to interpret the passed-in object and produce a string. If it's an NSValue instance, the question is what type of data that instance contains. Once you know that, you can write code to represent it as a string (similar to NSStringFromRect()).