software-mariodiana
8/31/2018 - 5:44 PM

Wrap an NSMutableArray, extending it to implement KVC compliance for a "count" property.

Wrap an NSMutableArray, extending it to implement KVC compliance for a "count" property.

/* Header: ItemStore.h

#import <Foundation/Foundation.h>

@interface ItemStore : NSObject <NSFastEnumeration>
@property (nonatomic, assign, readonly) NSUInteger count;
@end
*/

#import "ItemStore.h"

@interface ItemStore ()
@property (nonatomic, strong) NSMutableArray* array;
@property (nonatomic, assign, readwrite) NSUInteger count;
@end


@implementation ItemStore

- (instancetype)init
{
    self = [super init];
    
    if (self) {
        _array = [NSMutableArray array];
        _count = [_array count];
    }
    
    return self;
}


#pragma mark - Message forwarding to mutable array

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    if ([[self array] respondsToSelector:[anInvocation selector]]) {
        NSUInteger count = [[self array] count];
        
        [anInvocation invokeWithTarget:[self array]];
        
        if (count != [[self array] count]) {
            // If we instead set the count every time, we fire off a KVO when we don't want one!
            self.count = [[self array] count];
        }
    }
    else {
        [super forwardInvocation:anInvocation];
    }
}


- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
{
    NSMethodSignature* signature = [super methodSignatureForSelector:selector];
    
    if (!signature) {
        signature = [[self array] methodSignatureForSelector:selector];
    }
    
    return signature;
}


#pragma mark - Facilitate fast enumeration

- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state
                                  objects:(id __unsafe_unretained *)buffer
                                    count:(NSUInteger)len
{
    return [[self array] countByEnumeratingWithState:state objects:buffer count:len];
}

@end