wbyoung

Whitney Young is a developer at FadingRed
 

July 14th, 2009

KVC array accessors are notoriously a pain to implement. Really they are just wrapping a bunch of methods around a mutable instance variable, so every implementation is the same. All that’s different is the property name. It’s a shame that Objective-C 2.0 didn’t include an @property and @synthesize for to-many relationships. Until that happens, here’s a way to get something similar with macros:

/*!
 \breif     Allows easy definition of an array accessor
 \details   Must provide both the lowercase and uppercase (plural)
            name of the property being accessed
 */
#define array_property(low, up) \
- (NSArray *)low; \
- (NSInteger)countOf ## up; \
- (id)objectIn ## up ## AtIndex:(NSInteger)index; \
- (NSArray *) low ## AtIndexes:(NSIndexSet *)indexes; \
- (void)get ## up :(id *)buffer range:(NSRange)range; \
- (void)insertObject:(id)object in ## up ## AtIndex:(NSInteger)index; \
- (void)insert ## up :(NSArray *)objects atIndexes:(NSIndexSet *)indexes; \
- (void)removeObjectFrom ## up ## AtIndex:(NSInteger)index; \
- (void)remove ## up ## AtIndexes:(NSIndexSet *)indexes; \
- (void)replaceObjectIn ## up ## AtIndex:(NSInteger)index withObject:(id)object; \
- (void)replace ## up ## AtIndexes:(NSIndexSet *)indexes with ## up :(NSArray *)replacement;

/*!
 \breif     Allows easy definition of an array accessor
 \details   Storage must be an NSMutableArray instance variable.  You must alloc and dealloc
            this object yourself.  Must provide the name of the storage varable as well as
            the lowercase and uppercase (plural) name of the property being accessed
 */
#define array_synthesize(storage, low, up) \
- (NSArray *)low { return storage; } \
- (NSInteger)countOf ## up { return [storage count]; } \
- (id)objectIn ## up ## AtIndex:(NSInteger)index { return [storage objectAtIndex:index]; } \
- (NSArray *) low ## AtIndexes:(NSIndexSet *)indexes { return [storage objectsAtIndexes:indexes]; } \
- (void)get ## up :(id *)buffer range:(NSRange)range { [storage getObjects:buffer range:range]; } \
- (void)insertObject:(id)object in ## up ## AtIndex:(NSInteger)index { [storage insertObject:object atIndex:index]; } \
- (void)insert ## up :(NSArray *)objects atIndexes:(NSIndexSet *)indexes { [storage insertObjects:objects atIndexes:indexes]; } \
- (void)removeObjectFrom ## up ## AtIndex:(NSInteger)index { [storage removeObjectAtIndex:index]; } \
- (void)remove ## up ## AtIndexes:(NSIndexSet *)indexes { [storage removeObjectsAtIndexes:indexes]; } \
- (void)replaceObjectIn ## up ## AtIndex:(NSInteger)index withObject:(id)object { [storage replaceObjectAtIndex:index withObject:object]; } \
- (void)replace ## up ## AtIndexes:(NSIndexSet *)indexes with ## up :(NSArray *)replacement { [storage replaceObjectsAtIndexes:indexes withObjects:replacement]; }