objc-zen/objc-zen-book

Another way to add object to immutable collection

onmyway133 opened this issue · 1 comments

Hi, with KVC, we have another option mutableArrayValueForKey, mutableSetValueForKey to add object to the immutable collection

Extract from the Core Data 2nd book, section Mutable Access of To-Many Relationships

You might notice that the NSSet we get back when accessing a to-many rela- tionship is immutable. Adding an object to a to-many relationship with an immutable NSSet requires creating a mutable copy of the NSSet, adding the new object to the NSMutableSet, and setting the NSMutableSet back onto the parent object. It’s a painful process and, fortunately, unnecessary. When we want to add an object to a to-many relationship, we can use -mutableSetValueForKey: in the place of -valueForKey:. This returns an NSMutableSet for us that is already associated with the parent object and reduces our code to the following:

NSManagedObject *newIngredient = ...;
NSManagedObject *recipe = ...;
NSMutableSet *ingredients = [recipe mutableSetValueForKey:@"ingredients"]; 
[ingredients addObject:newIngredient];

Note that we did not need to set the NSMutableSet back into the entity, and therefore the code to add an object to a to-many relationship is quite short

What do you think?

Say you have a class like this

@interface User
@property (nonatomic, strong) NSArray *books;
@end

How do you add an object to books?

Probably I might not getting right the question but I will probably not have a class like the one you described.
I will rather do something like this:

@interface User
@property (nonatomic, readonly) NSArray *books;
- (void)addBook:(Book *)book
@end


@implementation User ()
@property (nonatomic, strong) NSMutableArray *mutableBooks;
@end


@implementation User

- (void)addBook:(Book *)book
{
    [self.mutableBooks addObject:book];
}

- (NSArray *)books
{
    return [self.mutableBooks copy];
}

@end

If you need or want to got for the extra mile inside addBook: you can implement thread safety logic to access the mutable array from different thread.

Exposing the array interface breaks the encapsulation and let the user of the class to fiddle with you internal representation that can eventually change in the future.