views:

62

answers:

1

I have a CoreData relationship set up as follows: (sorry, I'm new to stackoverflow so I have to draw it with ascii).


Story (object)

  • Attributes: creationDate, order,

  • Relationships: sentences (one to many with Sentence)

Sentence (object)

  • Attributes: image, order, text

  • Relationships: belongsTo (one to one with Story)


Notes:

  • the sentences relationship is an NSSet
  • the belongsTo relationship is a Story

Simply put, a Story has many Sentences, but a Sentence can only belong to one Story.

I'm having trouble effectively setting the belongsTo property - and I'm aware I'm missing the paradigm a bit. I'm afraid that when I set belongsTo I'll be creating another Story object with it's own NSSet, creating a recursive loop of doom. In any case, my problem appears to be effectively setting the belongsTo property / relationship of each sentence.

The code to insert my data into the CoreData repository looks like this:

-(void)addStoryItemAction:(Sentence*)sentence{

[self dismissModalViewControllerAnimated:YES];  
Story *story = [[Story alloc] initWithSentence: sentence];

sentence.belongsTo = story;

//crash and burn here.

Story *storySetter = (Story*)   [NSEntityDescription insertNewObjectForEntityForName:@"Story" inManagedObjectContext:managedObjectContext];
[storySetter setSentences:      story.sentences];
[storySetter setCreationDate:   story.creationDate];
[storySetter setOrder:          story.order];

NSError *error;  

BOOL isSaved = [managedObjectContext save:&error];
NSLog(@"isSaved? %@", (isSaved ? @"YES" :@"NO ") );

if (!isSaved) {
    NSLog(@"%@:%s Error saving context: %@", [self class], _cmd, [error localizedDescription]);
    return;
}

}

I get the following error when it runs:

-[Sentence setBelongsTo:]: unrecognized selector sent to instance 0x5b5aa00

I'm aware that I'm missing the point somewhere along the way - could someone clear up where I'm going wrong so that I can implement the insert of this CoreData set effectively?

FYI: Sentence.h:

 #import <Foundation/Foundation.h>
 #import "Story.h"

 @class Story;

 @interface Sentence : NSManagedObject {
 }
 @property (assign) NSString  *text;
 @property (assign) NSString  *image;
 @property (assign) NSInteger *order;
 @property (nonatomic, retain) Story  *belongsTo;

 - (id)initWithContent:(NSString*)sentenceText image:(NSString*)sentenceImage order: (NSInteger*)sentencePosition;
 @end

Sentence.m:

 #import "Sentence.h"
 @implementation Sentence
 @synthesize text;
 @synthesize image;
 @synthesize order;
 @dynamic belongsTo;

 - (id)initWithContent:(NSString*)sentenceText image:(NSString*)sentenceImage order: (NSInteger*)sentencePosition{
[self setText:  sentenceText];
[self setImage: sentenceImage];
[self setOrder: sentencePosition];  
return self;
 }
 @end

story.h

 #import <Foundation/Foundation.h>
 #import <CoreData/CoreData.h>
 #import "Sentence.h" 
 @class Sentence;
 @interface Story : NSManagedObject {
 }
 @property (assign) NSSet     *sentences;
 @property (assign) NSDate    *creationDate;
 @property (assign) NSInteger *order;

 - (id)initWithSentence:(Sentence*)sentence;
 @end

story.m

 #import "Story.h"
 @implementation Story
 @synthesize sentences;
 @synthesize creationDate;
 @synthesize order;

 - (id)initWithSentence: (Sentence*) sentence{

NSLog(@"initWithSencence: sentence: %@", sentence);
sentences = [[NSSet alloc] initWithObjects:sentence, nil];
//[sentences setByAddingObject:sentence];
[self setSentences:sentences];
NSLog(@"sentences (in story object): %@", sentences);
creationDate = [NSDate date];
[self setCreationDate:creationDate];
//later expansion, position should be max(position of all stories) ++
[self setOrder:0];

 return self;
 }

 @end
A: 

I'm a bit confused about why you're calling alloc / init on Story directly. I suspect that if you're doing the same thing elsewhere in your code (which you should publish for us to gawk at) then the "sentence" object passed in to addStoryItemAction: is probably NOT a properly initialized NSManagedObject.

The error you are encountering means that the underlying class has not properly implemented the accessors for that property "belongsTo", so it would seem something went afoul in your initialization code. You should be using:

NSEntityDescription *entityFromModel = [[aModel entitiesByName] valueForKey:@"Sentence"];
Sentence *sentence = (Sentence *)[[NSManagedObject alloc] initWithEntity:entityFromModel insertIntoManagedObjectContext:context];
ImHuntingWabbits
Hey IHW, thanks for the answer. I won't have a chance to try out your answer for a couple days, but I'm looking forward to seeing if the answer will fix up where I'm going wrong. In the meantime, as you've requested I've added extra relevant code - hope that clarifies things a bit. Cheers again!
glenstorey
From looking at the implementation files you're definitely missing calls to the NSManagedObject's designated initializer initWithEntity:insertIntoManagedObjectContext. A suitable remedy (if you still wanted to use those wrappers) would be to change them to take a managed object context argument and call [super initWithEntity:anEntityDescription insertIntoManagedObjectContext:passedInContext].
ImHuntingWabbits
Thanks IHW, I used the initWithEntity statement rather than my own initializer and now I'm working fine. Thanks for your answer!
glenstorey