What I'm doing
Using RestKit, I'm making a GET request to get a JSON object that contains an array of User objects that populate a UITableView. I pass that array into a private NSArray called users which becomes _users (I'm still fuzzy on this). This works, and the table populates fine. I can access the individual objects in the _users array from my other methods, such as [UITableViewCell cellForRowAtIndex].
However, at the same time I pull the data down, and before I call [self.tableView reloadData] from inside the success block of [RKObjectManager getObjectsAtPath...], I want to process the individual objects a little bit.
My problem
Using [RKObjectManager getObjectsAtPath parameters success failure], success returns the RKMappingResult as expected, and I pass its array to a _users, which populates my UITableView. This works, but in the same success block, I try NSLog'ing _users[i] and it returns *nil description*. I know the values are being set at some point, because I populate my UITableViewCells by calling _users[i] in another method.
Hopefully more helpful info
When I NSLog(#"%#", _users) from inside the success block, and know for a fact there are 3 objects in the array, I see:
(
(null),
(null),
(null)
).
I can provide more info, I'm just not sure what to put. I can also show my code, but it's basically out of the book from the RestKit docs.
User object
#interface User : NSObject
#property (nonatomic, strong) NSString *id;
#property (nonatomic, strong) NSString *email;
#property (nonatomic, strong) NSString *username;
#property (nonatomic, strong) NSString *fullName;
#property (nonatomic, strong) NSString *bio;
#property (nonatomic) NSDate *dob;
#property (nonatomic, strong) NSString *avatar;
#property (nonatomic, strong) NSString *avatarMeta;
#property (nonatomic, strong) NSString *location;
#property (nonatomic, strong) NSURL *url;
#property (nonatomic, strong) NSString *enabled;
#end
RKObjectManager example
*note - some pieces have been removed for security reasons
- (void)loadUsers {
NSMutableDictionary *params = [[NSMutableDictionary alloc] initWithDictionary:#{#"token": self.token}];
NSString *path = #"/api/v1/g/feed";
if ( self.cursor ) {
path = [NSString stringWithFormat:#"%#/%#", path, self.cursor];
}
[[RKObjectManager sharedManager] getObjectsAtPath:path
parameters:params
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
_users = mappingResult.array;
NSLog(#"Last User: %#",_users[0]); // *nil description*
NSLog(#"Array: %#", _users); // ((null),(null),(null),(null),(null),(null),(null),(null),(null),(null))
[self.tableView reloadData]; // table gets populated correctly
}
failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"No feed available: %#", error);
}];
}
Most likely you're overriding the description method, probably by adding your own property with that name, in the user class and setting that to an empty string. This breaks everything. You should rename that property to overview or something like that and update your usage.
Related
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.
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.
I am using the DynamoDB SDK v2 . I can scan the database however I am struggling to query it for a specific results. I don't know if I have the DB setup wrong or I am doing the query wrong.
When I use
- (void)getTableRow:(NSString *)rangeKey {
AWSDynamoDBObjectMapper *dynamoDBObjectMapper = [AWSDynamoDBObjectMapper defaultDynamoDBObjectMapper];
[[dynamoDBObjectMapper load:[SonicUserTableRow class]
hashKey:#"UserId"
rangeKey:rangeKey] continueWithExecutor:[BFExecutor mainThreadExecutor] withBlock:^id(BFTask *task) {
if (!task.error) {
SonicUserTableRow *tableRow = task.result;
NSLog (#"Table Row %#", tableRow);
} else {
//Catch Error
}
return nil;
}];
}
I am calling it using [self getTableRow:#" ENTER UNIQUE USER ID "];
However I am getting the error
The provided key element does not match the schema
How can I fix this?
Note I am using the new Amazon SDK v2.
My Database
HASH & RANGE KEYS
SonicUserTableRow .m
+ (NSString *)dynamoDBTableName {
return #"SonicUsers";
}
+ (NSString *)hashKeyAttribute {
return #"UserId";
}
+ (NSString *)rangeKeyAttribute {
return #"Username";
}
SonicUserTableRow .h
#interface SonicUserTableRow : AWSDynamoDBModel <AWSDynamoDBModeling>
#property (nonatomic, strong) NSString *UserId;
#property (nonatomic, strong) NSString *Username;
#property (nonatomic, strong) NSString *profileImage;
#property (nonatomic, strong) NSString *active;
#property (nonatomic, strong) NSString *email;
#property (nonatomic, strong) NSString *flags;
#property (nonatomic, strong) NSString *attuned;
I have UserId value UserIdString: us-east-1:4ae0a93a-59a6-45fd-80c8-ff6b99f1d152 in the database so am trying to call for example: [self getTableRow:#"us-east-1:4ae0a93a-59a6-45fd-80c8-ff6b99f1d152"];
If DropId is a hash key of your table, you can use - load:hashKey:rangeKey: to load a single item.
I've been trying to map the following object from the JSON response and from everything I see in the console output, there isn't any reason why the mapping isn't successful - I appreciate if anyone could have a check and see:
#interface RKElectionsModel : NSObject
#property (nonatomic, assign) bool isActive;
#property (nonatomic, strong) NSNumber *electionID;
#property (nonatomic, strong) NSString *title;
#property (nonatomic, strong) NSString *summary;
#property (nonatomic, strong) NSNumber *availableSeats;
#property (nonatomic, strong) NSNumber *candidatesCount;
#property (nonatomic, strong) NSNumber *withdrawnCount;
#property (nonatomic, strong) NSSet *candidates;
#end
/**
* Election Detail Mapping: Getting all election details, we have some extra information from
* the API call
*
*/
RKObjectMapping *electionDetailsMapping = [RKObjectMapping mappingForClass:[RKElectionsModel class]];
// Map JSON -> entities
[electionDetailsMapping addAttributeMappingsFromDictionary:#{
#"id": #"electionID",
#"title": #"title",
#"summary": #"summary",
#"active": #"isActive",
#"availableSeats": #"availableSeats",
#"candidatesCount": #"candidatesCount",
#"withdrawnCount": #"withdrawnCount"
}];
// Register our mappings with the provider
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:electionDetailsMapping pathPattern:#"/api/elections/:electionID/all" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
Console output on pastebin and any examples of the JSON response you can visit here
Appreciate any help,
Lewis
Seems like your trying to map a NSString to NSNumber.
In your NSObject try to add the following validation and transform the string you receive from the server to a NSNumber when the mapping starts.
- (BOOL)validateAvailableSeats:(id *)ioValue error:(NSError **)outError {
// Force the value to be a NSNumber
*ioValue = [NSNumber numberWithDouble:[(NSString*)value doubleValue] ]
return YES;
}
In the RestKit Wiki you'll find more transformations for your values.
I have successfully post the object on my wall with its default values for the properties.
What I need to do now is setting these properties for that object manually through my code.
Here is what I have done:
#protocol OGApple<FBOpenGraphAction>
#property (nonatomic, retain) NSString *url;
#property (nonatomic, retain) NSString *title;
#property (nonatomic, retain) NSString *image;
#property (nonatomic, retain) NSString *description;
#end
#protocol OGEatAction<FBOpenGraphAction>
#property (retain, nonatomic) id<OGApple> apple;
#end
the object "apple" here has four required properties (url, title, image, description) ,,, here is how I set them :
Define the object:
id<OGApple> graphObject = (id<OGApple>)[FBGraphObject graphObject];
Define the action:
id<OGEatAction> action = (id<OGEatAction>)[FBGraphObject graphObject];
set the properties (I have try method 1 and two) none of them set the object property :
Method one:
[graphObject setObject:#"The Game" forKey:#"title"];
[graphObject setObject:#"https://raw.github.com/fbsamples/ios-3.x-howtos/master/Images/iossdk_logo.png" forKey:#"image"];
[graphObject setObject:#"http://samples.ogp.me/267255650070428" forKey:#"url"];
Method two:
graphObject.url = #"http://samples.ogp.me/267255650070428";
graphObject.title = #"Mohammad";
graphObject.image = #"https://raw.github.com/fbsamples/ios-3.x-howtos/master/Images/iossdk_logo.png";
then assign the object to the action:
action.apple = graphObject;
then POST the request
[FBRequestConnection startForPostWithGraphPath:#"me/theapp:eat"
graphObject:action
completionHandler:^(FBRequestConnection *connection,
id result,
NSError *error) {
// handle the result
if(error)
NSLog(#"%#", error);
else
NSLog(#"%#", result);
}];
The request successfully posted and return id = xxxxxxxxxx
But on my timeline the object not take the parameters that I have passed to it!
Did I miss something or need any extra config on a server?
Thanks in advance :)