one to many relationship not working (Restkit 0.20) addRelationshipMappingWithSourceKeyPath - restkit

I have a simpe one to many relationshipim my JSON and would like to map this into Objects (NOT Core Data entities). Mapping the poducts is working fine. But every product has an array of tracks that is not mapped.
This is the JSON:
Here is the code:
Product.h
#import <Foundation/Foundation.h>
#interface Product : NSObject
#property (nonatomic, strong) NSString* productid;
#property (nonatomic, strong) NSString* title;
#property (nonatomic, strong) NSString* artist;
//...
#property (nonatomic, strong) NSMutableArray *tracks;
Track.h
#import <Foundation/Foundation.h>
#interface Track : NSObject
#property (nonatomic, strong) NSString *artist;
#property (nonatomic, strong) NSString *title;
#property (nonatomic, strong) NSString *mixversion;
Here the code to request the JSON and map the response to Objects
/// Create Mappers for Product and Track
RKObjectMapping *mappingForProduct = [RKObjectMapping mappingForClass:[Product class]];
[mappingForProduct addAttributeMappingsFromArray:#[#"productid", #"title", #"tracks"]];
RKObjectMapping *mappingForTrack = [RKObjectMapping mappingForClass:[Track class]];
[mappingForTrack addAttributeMappingsFromArray:#[#"artist",#"title",#"mixversion"]];
/// assign relationship product-track
[mappingForProduct addRelationshipMappingWithSourceKeyPath:#"tracks" mapping:mappingForTrack];
/// setup responseDescriptor
NSString *key_path = #"products";
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mappingForProduct
pathPattern:nil
keyPath:key_path
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
/// Create Manager, connect responseDescriptor and execute
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:#"myRequestString"]];
[manager addResponseDescriptor:responseDescriptor];
[manager getObject:nil path:#"" parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult)
{
self.productsArray = [NSMutableArray arrayWithArray:mappingResult.array];
}
failure:^(RKObjectRequestOperation *operation, NSError *error)
{
NSLog(#"Error: %#", error);
}
This gives an assertion error:
*** Assertion failure in -[RKObjectMapping addPropertyMapping:], /Users/.../Pods/RestKit/Code/ObjectMapping/RKObjectMapping.m:235
The magic should happen in this line:
[mappingForProduct addRelationshipMappingWithSourceKeyPath:#"tracks" mapping:mappingForTrack];
... but for some reason it doesn't.
I've searched quite some sources on SO and the documentation, tried quite some combinations of keypath changed, but nothing will give the required result. A lots of the availble sample code is regarding older versions of RestKit or deals with Core Data. I just want to get mapped objects, no Core Data entities.
Thanks in advance for any hint.

You're just trying to add a mapping for tracks twice. It should be a relationship mapping, not an attribute mapping. Change the mappingForProduct to:
[mappingForProduct addAttributeMappingsFromArray:#[#"productid", #"title"]];
And the cause of the exception should be removed.

Related

many-to-one relation core data

I am obviously new in Core Data, I have read quite a lot about the topic from Apple and from countless other sources. However, none seems to treat the many-to-one relation in a way for a newbie like me to understand. I seems to be fine with one-to-one relation, but I have some difficulties on understanding many-to-one relation.
My problem is as follow:
I am working on a small project to practice Core Data. In my project, there are two entities:Person and Note and they are related as follow:
(Sorry, couldn't add the picture)
A Person can have several notes, but Note can only have one owner, Person. Person entity is related with a one-to-many relation (double arrows pointing to the entity: Note), while the entity Note is related with a many-to-one (single arrow pointing to Person)
This is what I have so far:
Note.h
#class Person;
#interface Note : NSManagedObject
#property (nonatomic, retain) NSDate * noteCreateDate;
#property (nonatomic, retain) NSString * noteUser;
#property (nonatomic, retain) Person *person;
Person.h
#class Note, Organise;
#interface Person : NSManagedObject
#property (nonatomic, retain) NSString * personAddress;
#property (nonatomic, retain) NSData * personAvatar;
#property (nonatomic, retain) NSString * personBDay;
#property (nonatomic, retain) NSDate * personFutureDate;
#property (nonatomic, retain) NSString * personGender;
#property (nonatomic, retain) NSString * personName;
#property (nonatomic, retain) NSString * personRelation;
#property (nonatomic, retain) NSSet *notes;
#property (nonatomic, retain) NSSet *organises;
#end
#interface Person (CoreDataGeneratedAccessors)
- (void)addNotesObject:(Note *)value;
- (void)removeNotesObject:(Note *)value;
- (void)addNotes:(NSSet *)values;
- (void)removeNotes:(NSSet *)values
In my view controller I am trying to save the notes as follow:
NSManagedObjectContext *context = [self managedObjectContext];
Note *newNote;
newNote = (Note *) [NSEntityDescription insertNewObjectForEntityForName:#"Note" inManagedObjectContext:context];
// Saving the notes
newNote.noteUser = noteTextView.text;
newNote.noteCreateDate = added;
[newNote setPerson:newNote.person];
///////////////Saving to the DataBase /////////
NSError *error = nil;
if ([self.managedObjectContext hasChanges]) {
if (![self.managedObjectContext save:&error]) { //save failed
NSLog(#"Save Failed: %#", [error localizedDescription]);
}
else {
NSLog(#"Save Succeeded");
}
}
It is saving the data in the database fine, but the problem is: There is no relationship between Person and Notes in the database. The column for person in the database is empty (not showing to whom the note belong to).
I have tried several things to try to link the person with the note, NONE of them seems to work. So, it seems that I am stucked and I would very much appreciate some help.
This is the latest tutorial I used for help:
http://brandontreb.com/core-data-quicktip-inverse-relationships
https://itunes.apple.com/fr/itunes-u/advanced-iphone-development/id407243028?l=en&mt=10
Thank you.
Your code does not create any relationship between the Note and a Person. This:
[newNote setPerson:newNote.person];
is the same as newNote.person = newNote.person; and does not change anything.
You must create a Person object (or fetch an existing Person) and then set
newNote.person = thePerson;
to establish the relationship.

Adding objects to array NSXMlParser no data

I'm trying to make a XML-parser that saves data from YR.no-API. The parser should add data to these two datastructures. My problem is when i try to add a WeatherTimeData object to my array in WeatherData, it seems like the objects doesnt get added, the following count always give me zero
- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementname namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementname isEqualToString:#"time"])
{
[self.weatherdata.timedata addObject:currentWeatherTimeData];
NSLog(#"amount of objects in timedata-array %d", [[self.weatherdata timedata] count]);
}
These are my two data-structures, i alloc weatherData in the following method
-(id) loadXMLByURL:(NSString *)urlString
{
_weatherdata = [[WeatherData alloc] init];
NSURL *url = [NSURL URLWithString:urlString];
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
parser = [[NSXMLParser alloc] initWithData:data];
parser.delegate = self;
[parser parse];
return self;
}
Do i have to alloc the array inside of the weatherdata object?
WeatherData.h
#interface WeatherData : NSObject
#property (strong, nonatomic)NSString *town;
#property (strong, nonatomic)NSString *country;
#property (strong, nonatomic)NSMutableArray *timedata;
#end
WeatherData.m
#implementation WeatherData
#synthesize town = _town;
#synthesize country = _country;
#synthesize timedata = _timedata;
#end
WeatherTimeData.h
#interface WeatherTimeData : NSObject
#property (strong, nonatomic)NSDate *startTime;
#property (strong, nonatomic)NSDate *endTime;
#property (strong, nonatomic)NSString *iconSymbol;
#property (strong, nonatomic)NSString *windDirection;
#property (strong, nonatomic)NSString *windSpeed;
#property (strong, nonatomic)NSString *temprature;
#property (strong, nonatomic)NSString *preassure;
#end
WeatherTimeData.m
#implementation WeatherTimeData
#synthesize startTime = _startTime;
#synthesize endTime = _endTime;
#synthesize iconSymbol = _iconSymbol;
#synthesize windDirection = _windDirection;
#synthesize windSpeed = _windSPeed;
#synthesize temprature = _temprature;
#synthesize preassure = _preassure;
#end
This type of problem is classically because the object hasn't been allocated, and given Objective-C allows messages to be sent to nil the programmer doesn't notice.
I think it would be nice to be able to provide a runtime environment variable where such events are logged to stdout...
I would suspect that [WeatherTimeData init] isn't creating timedata and that's because you haven't provided an implementation for it; just using #sythensize isn't enough to create the objects.

RestKit Mapping Error "Cannot map a collection of objects onto a non-mutable collection."

Okay, so I have this code that I'm using to map data from a JSON API. Everything runs fine, but then I get this error:
restkit.object_mapping:RKMapperOperation.m:76 Adding mapping error: Cannot map a collection of objects onto a non-mutable collection. Unexpected destination object type '__NSDictionaryI'
Here is the code I'm using for the mapping
RKObjectManager *objectManager = [[RKObjectManager alloc] initWithHTTPClient:client];
RKObjectMapping *classMapping = [RKObjectMapping mappingForClass:[GradePeriod class]];
[classMapping addAttributeMappingsFromDictionary: #{
#"period" : #"period",
#"class" : #"name",
#"term" : #"term",
#"teacher" : #"teacher",
#"percent" : #"percent",
#"grade" : #"grade",
#"missing" : #"missing",
#"update" : #"update",
#"detail" : #"url"
}];
// Create a Response Descriptor
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:classMapping
pathPattern: nil
keyPath: #"grades"
statusCodes:[NSIndexSet indexSetWithIndex:200]];
[objectManager addResponseDescriptor:responseDescriptor];
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
NSDictionary *queryParams;
queryParams = [NSDictionary dictionaryWithObjectsAndKeys:username, #"username", password, #"password", nil];
// Retrieve the Data
[objectManager postObject:queryParams
path:#""
parameters:queryParams
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
grades = [NSMutableArray arrayWithArray: [mappingResult array]];
NSLog(#"Loaded Grades: %#", grades);
[self.tableView reloadData];
}
failure:^(RKObjectRequestOperation *operation, NSError *error) {
// Stuff removed for easier reading
}];
Grades is an NSMutableArray
#property (nonatomic, retain) NSMutableArray *grades;
GradePeriod is defined like this
#property (strong, nonatomic) NSString *period;
#property (strong, nonatomic) NSString *name;
#property (strong, nonatomic) NSString *term;
#property (strong, nonatomic) NSString *teacher;
#property (strong, nonatomic) NSString *percent;
#property (strong, nonatomic) NSString *grade;
#property (strong, nonatomic) NSString *missing;
#property (strong, nonatomic) NSString *update;
#property (strong, nonatomic) NSString *url;
I'm not sure what I'm doing wrong.
Thanks so much!
I upgraded to the latest version of RestKit and it fixed itself.

Declare a Mutable Dictionary (to use addEntriesFromDictionary) in header file

I need to use several times:
[mutableDict addEntriesFromDictionary:dictionary];
I don't know how to declare mutableDict in the header file. I try with:
#property (nonatomic, assign) NSMutableDictionary *mutableDict;
#property (nonatomic, retain) NSMutableDictionary *mutableDict;
#property (nonatomic, retain, readwrite) NSMutableDictionary *mutableDict;
And more...
How I must to declare this NSMutableDictionary??
In your header file use #property (nonatomic, retain) NSMutableDictionary *mutableDict; if your are not using ARC, or #property (nonatomic, strong) NSMutableDictionary *mutableDict; if you are using ARC.
In your implementation include #synthesize mutableDict; or better #synthesize mutableDict = _mutableDict; somewhere after #implementation YourClass.
You should also initialize it with something like _mutableDict = [[NSMutableDictionary alloc] init];
If you do not need your mutable dictionary used from outside (ex: [myobject.mutableDict addEntriesFromDictionary:dictionary]; you better not define it in your header file but in your implementation like:
#implementation YourClass {
NSMutableDictionary *_mutableDict;
}
and initialize it like shown above

NSAttributedString as a Transformable Attribute in Core Data Entity

In the Core Data Programming Guide under "Transformable Attributes" here.
It is stated "You can now use the attribute as you would any other standard attribute, as illustrated in the following code fragment:"
The follow line of code is listed newEmployee.favoriteColor = [NSColor redColor];
I am trying to do something similar in my code but it doesn't work. Here is my code:
In Entry.h:
#interface Entry : NSManagedObject
{
}
#property (nonatomic, retain) NSAttributedString * contentString;
#property (nonatomic, retain) NSDate * date;
#property (nonatomic, retain) NSManagedObject * journal;
#end
and in Entry.m:
#implementation Entry
#dynamic contentString;
#dynamic date;
#dynamic journal;
- (void)awakeFromInsert {
[super awakeFromInsert];
self.date = [NSDate date];
}
#end
Elsewhere I have this code:
Entry *newEntry =
[NSEntityDescription insertNewObjectForEntityForName:#"Entry"
inManagedObjectContext:[self managedObjectContext]];
newEntry.contentString = [[[NSAttributedString alloc] initWithString:#"MyString"] autorelease];
newEntry.journal = self.journal;
The line
newEntry.contentString = [[[NSAttributedString alloc] initWithString:#"MyString"] autorelease];
is equivalent to
newEmployee.favoriteColor = [NSColor redColor];
As far as I can tell however this doesn't work. I get a runtime error:
2010-10-13 09:02:08.577 JournalMaker[2437:a0f] Cannot create NSData
from object MyString{ } of class NSConcreteAttributedString
I have no idea what this error message is supposed to mean. Can someone explain?

Resources