1
votes

I got few entities for an iOS App which are linked by relations. To make a simple example, lets assume we got a relation like this (one-to-many):

company <--->> person

I'm using xcode 4.6 and the core data modelling tool for model generation, so I end up with

//Company.h
@class Person;
@interface Company : NSManagedObject
@property (nonatomic, retain) NSString * company_name;
@property (nonatomic, retain) NSNumber *has_changed;
@property (nonatomic, retain) NSSet *person;
@end

@interface Company (CoreDataGeneratedAccessors)
- (void)addPersonObject:(Person *)value;
- (void)removePersonObject:(Person *)value;
- (void)addPerson:(NSSet *)values;
- (void)removePerson:(NSSet *)values;
@end

//Company.m
#import "Company.h"
#import "Person.h"

@implementation Company
@dynamic company_name;
@dynamic has_changed;
@dynamic person;
@end

And

//Person.h
@class Company;

@interface Person : NSManagedObject
@property (nonatomic, retain) NSString * first_name;
@property (nonatomic, retain) NSString * last_name;
@property (nonatomic, retain) Company *company;
@end

//Person.m
#import "Person.h"
#import "Company.h"

@implementation Person
@dynamic first_name;
@dynamic last_name;
@dynamic company;
@end

Now, suppose I want to set the boolean (implemented as NSNumber in Core Data) attribute has_changed to TRUE every time one of the following occurs:

  • a attribute of the company entity is changed, except the has_changed attribute itself of course (since this would cause a loop)
  • a attribute of the person entity is changed

What would be the best (easy to implement + fast to process) way to implement something like this? For what I was able to find out, is that there are two options:

However, everything I find related to this topic seems to be outdated because of the changes in objective-c 2.0, core-data / cocoa or iOS. For example, automatically generating the accessor methods by using the core-data modelling editor dosn't seem to work when using xcode 4.6 with ARC enabled, since everything I get pasted are the @dynamic lines which core-data generates anyways (see code example above).

Also I find it a bit confusing what the documentation says. What would be the best way to implement this? KVO? Custom accessors? Bit of both or even something compleatly different? And how would a possible implementation look like for the given example?

1
What have you found that indicates that KVO is outdated? - Wain
Not KVO in general, but in special when used within entity classes. What I mean is that I'm not sure what's the "right" way to do it and where to place the KVO implementation: within the entity? Within a service/controller class? Or better use custom accessor methods within the entity? What about the child entity: should I use a observer looking for the parent entity there or should I write custom accessors and within them manipulate the parents has_changed attribute? - omni
@Inafziger the example you linked to dosn't use ARC nor core-data. I agree that it might be a good general answer about KVO, but my question is not about KVO but about if KVO or custom core-data accessor methods or a combination of both is the way to go for the given example. - omni

1 Answers

1
votes

You could do this as such:

@implementation Company
// ...

- (void) didChangeValueForKey: (NSString *) key
{ 
   [super didChangeValueForKey: key];
   if (! [key isEqualToString: @"has_changed"])
     self.has_changed = YES;
}

// ...
@end

and similar for Person though the company property. You'd also want to implement didChangeValueForKey:withSetMutation:usingObjects:

Note that this suggestion does not address the common need of having a controller know about a change. There are other ways to do that.