The functionality of FBGraphObject is quite useful, accessing and setting the NSMutableDictionary via dot notation is a nice feature to have. More info from here.
I have a protocol Duck.
#protocol Duck <FBGraphObject>
#property (nonatomic, strong) NSNumber *objectID; // id key
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSString *description;
#end
// Now I can do this.
NSDictionary *anAnimal = #{#"id":#1, #"name":#"donald", #"description":#"Its a duck that talks!!"};
NSMutableDictionary <Duck> *aDuck = (NSMutableDictionary <Duck> *) [FBGraphObject graphObjectWrappingDictionary:anAnimal];
NSLog(#"aDuck name via Key: %#",[aDuck objectForKey:#"name"]);
NSLog(#"aDuck name via Dot Notation: %#",aDuck.name);
NSLog(#"aDuck description via Key: %#",[aDuck objectForKey:#"description"]);
NSLog(#"aDuck description via Dot Notation: %#",aDuck.description);
The code above works fine.
So my question is, are there any issues/problem when using the FBGraphObject outside the scope of FacebookSDK, Just like the code above?
Related
I use JSONModel to hold my app datasource, and use -(id)initWithArray:(NSArray *)array modelClass:(Class)cls generated an JSONModelArray, now I want to do some search stuff like enumerateObjectsUsingBlock: method does. But I found that JSONModelArray is not inherited from NSArray.
So, how can I do this?
Try use BWJSONMatcher to convert json string to a NSArray.
For example, your json string seems like :
[{"name":"Arron","age":20,"grade":2},{"name":"Burrows","age":21,"grade":2}]
All you have to do is declare your own data model:
#interface Student : NSObject
#property (nonatomic, strong) NSString *name;
#property (nonatomic, assign) NSInteger age;
#property (nonatomic, assign) NSInteger grade;
#end
BWJSONMatcher will help you convert it to a NSArray in a very neat way:
NSArray *students = [BWJSONMatcher matchJSON:jsonString withClass:[Student class]];
Heyo Guys
So I am more or less new to Objective C and got to a problem which I seem unable to solve.
I created a class called "Students" which all have a name surname etc. All those Students are put into a NSMutableArray (before they get created from JSON , that seems to work without a problem though). Then all the names of the students are put into a ListView. Afterwards when a name is clicked (segue passes the object), one should see the details of said student (i.e. his full name, his id, his street).
The problem is that all the string values of the student object seem to get lost.
I checked that all the student object work just fine. I think the problem lies at the #property in my student class.
Any comments and suggestions are appreciated
This is an excerpt of student.h As said only the string values get lost, the int (here the plz value) remains correct
#property (nonatomic, weak)NSString *lastname;
#property (nonatomic, weak)NSString *surname;
#property (nonatomic, weak)NSString *street;
#property (nonatomic, assign)int plz;
EDIT:
Here is where i parse my json.
for (NSDictionary *dic in jsonArray){
NSNumber *identity = [dic valueForKey:#"id"] ;
NSString *firstName = (NSString*) [dic valueForKey:#"first_name"];
NSString *lastName = (NSString*) [dic valueForKey:#"last_name"];
NSString *street = (NSString*) [dic valueForKey:#"street"];
NSNumber *plz = [dic valueForKey:#"plz"] ;
NSString *birth = (NSString*) [dic valueForKey:#"date_of_birth"];
NSArray *bills = dic[#"bills"];
NSArray *hours = dic[#"hours"];
NSLog(#"First %#",firstName);
Student *student = [[Student alloc]initWithLastName:lastName withSurname:firstName withStreet:street withPLZ:plz withOrt:#"Uitikon" withBirthDate:birth withOccupation:#"Schüler"];
[ApprenticeList addObject:student];
}
EDIT 2 :
I found out that the string values get lost even before the segue. All these objects are created in
ViewDidLoad
But in
prepareforsegue
all the values are allready null (except for the int) .So the only place where the student objects work is in
ViewdidLoad
#property (nonatomic, weak)NSString *lastname;
#property (nonatomic, weak)NSString *surname;
#property (nonatomic, weak)NSString *street;
change to
#property (nonatomic, strong)NSString *lastname;
#property (nonatomic, strong)NSString *surname;
#property (nonatomic, strong)NSString *street;
You can also use 'copy'. It will cause the setter for that property to create a copy of the object, otherwise it is identical to strong.
Let us say I have an NSObject Class Person.
#interface Person : NSObject
#property NSString *id;
#property NSString *name;
#property Address *billingAddress;
#end
#interface Address : NSObject
#property NSString *lane;
#property NSString *country;
#property NSString *zip;
#end
Now when I fetch the response from a URL, the response is in the form:
{
"response":
{
"Persons":[{"id":"2232","name":"John","Address":{"lane":"Adelaide Avenue","country":"Canada","zip":"45503"}}{"id":"3422","name":"Jane","Address":{"lane":"Victoria Avenue","country":"Australia","zip":"34903"}}]
}
}
I want to parse the response directly into objects without having to write a method to read and assign objects from NSDictionary. Is there are no objects to parse directly from the response to Object based on the Object parameters similar to "GSon" in Android.
EDIT:
I have used the below code to have generic class that does the job for strings without having to know about the object itself.
for (NSString *key in [dct allKeys]) {
if ([cat respondsToSelector:NSSelectorFromString(key)]) {
[cat setValue:[dct valueForKey:key] forKey:key];
}
}
There is no such magic, not even in Android's GSon!!!
Some where down the line you need to write code for converting JSON to your object.
You may create a generic class, or a method (just once) to convert all dictionary values to your object.
After some digging I did get a JSON framework that does exactly what I wanted - JSONModel.
We just need to specify Models and relationships and all the logic for converting JSON response to the models is handled by the framework. Very handy.
Basic usage :
Consider you have a JSON response like
{"id":"10", "country":"Germany", "dialCode": 49, "isInEurope":true}
The corresponding model will be
#import "JSONModel.h"
#interface CountryModel : JSONMode
#property (assign, nonatomic) int id;
#property (strong, nonatomic) NSString* country;
#property (strong, nonatomic) NSString* dialCode;
#property (assign, nonatomic) BOOL isInEurope;
#end
We don't need to write additional code in the .m file to parse and assign values to the variables. Now to initialise the model from the response we just need to do the below
NSString* json = (fetch JSON here)
NSError* err = nil;
CountryModel* country = [[CountryModel alloc] initWithString:json error:&err];
The works well with complex data structures as well.
I have complex JSON handling large amount of data, I need to optimise network traffic by sending only required attributes of mapped object to server.
For simplicity lets say I have following User class :
#property (nonatomic, retain) NSString *email;
#property (nonatomic, retain) NSString *fname;
#property (nonatomic, retain) NSString *password;
#property (nonatomic, retain) NSString *profilePic;
#property (nonatomic, retain) NSString *sname;
#property (nonatomic, retain) NSString *status;
#property (nonatomic, retain) NSString *token;
#property (nonatomic, retain) NSString *username;
#property (nonatomic, retain) NSNumber *isLoggedIn;
#property (nonatomic, retain) NSDate *dateCreated;
and my attributes mapping dictionary is following :
[dic addEntriesFromDictionary:#{
#"fname": #"fname",
#"sname": #"sname",
#"profilePic": #"profilePic",
#"email": #"email",
#"username": #"username",
#"password": #"password",
#"status": #"status",
#"token": #"token",
#"isLoggedIn": #"isLoggedIn",
#"dateCreated": #"dateCreated"
}];
For Signin call I needs to post just username & password as following JSON :
{
"user": {
"password": "password",
"username": "demouser"
}
}
While for Signup call I needs to POST entire User object so I cant downsize mapping dictionary. I needs to apply same procedure to lot more complex JSON.
How can I send required attributes of an object in POST call on conditional basis in an optimal fashion?
Thanks.
You are free to create multiple mappings for the same class / entity type - there is no restriction. Each mapping is associated with other mappings / request descriptor / response descriptor and this is where you need to concentrate on identification and uniqueness.
It may be simplest for you to have one request mapping which covers all of the attributes, and whose class is NSDictionary. Then, to use this mapping for a request you use KVC (dictionaryWithValuesForKeys:) to extract only the keys of interest from your true source object into a dictionary that you can then supply to the object manager for mapping and transmission.
Trying to store value in NSDictionary and retrieve it
Objects
#import <Foundation/Foundation.h>
#class ATTTEstOBJ;
#interface ATTTEst : NSObject
#property (nonatomic, retain) NSString *string1;
#property (nonatomic, retain) NSString *string2;
#property (nonatomic, retain) ATTTEstOBJ *obj1;
#end
#interface ATTTEstOBJ : NSObject
#property (nonatomic, retain) NSString *string3;
#property (nonatomic, retain) NSString *string4;
#property (nonatomic, retain) NSString *array1;
#end
I know it needs to be encoded properly to save and retrieve values.but In this case it is a composite object and I have no idea, how to deal it with.
- (void) encodeWithCoder: (NSCoder *)coder
So TLDR , How to save the composite value into dictionary and retrieve it back
I want to store ATTTest into a dictionary and retrieve it back.
EDIT : Detailed explanation
ATTTEst *test=[[ATTTEst alloc]init];
test.string1=#"a";
test.string2=#"b";
ATTTEstOBJ *obj=[[ATTTEstOBJ alloc]init];
obj.string3=#"c";
obj.string4=#"d";
test.obj1=obj;
NSMutableDictionary *dict=[[NSMutableDictionary alloc]initWithCapacity:3];
[dict setObject:test forKey:#"test"];
NSLog(#"%#",dict);
ATTTEst *tester=[dict objectForKey:test];
NSLog(#"%#",tester.obj1.string3);
IT shows null.as output I want to get the value as c for tester.obj1.string3
ATTTEst *tester=[dict objectForKey:test];
should be
ATTTEst *tester=[dict objectForKey:#"test"];
You have used the object test (instead of the string #"test") as key when retrieving the object. I don't think that
was intentionally.
In order to store them into NSDictionary, you don't need to encode them.
Just do:
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:, attestObject,#"attestObject", attest2Object,#"atttest2" nil];
Where attestObject and attest2Object are the objects you want to store, and strings are their keys.
This has nothing to do with encoding...