renaesop/blog

《Cocoa编程开发者手册》阅读笔记(一)

Opened this issue · 0 comments

该书有点年代,讲的OC都是不带ARC的。用Xcode9的话,书中的例子甚至都不能通过编译,网上也鲜有人提及修改的方法,在此把折腾的东西做个记录。

P87 中提及了“利用该机消息枚举”,实质是给容器生成一个代理对象,而向代理对象发送消息的话会将消息转发到容器中的每一个对象,并将调用的结果存入数组中返回。

修改后可通过编译的代码如下:

NSArray+map.h

#import <Foundation/Foundation.h>
@interface NSArray (AllElements)
- (id) map;
@end

@interface NSArrayMapProxy: NSProxy {
    NSArray* array;
}
-  (instancetype) initWithArray: (NSArray*) anArray;
@end

NSArray+map.m

#import "NSArray+map.h"
@implemetation NSArray (AllElements) 
- (id) map {
    return [[NSArrayMapProxy alloc] initWithArray: self];
 }

@end



@implemetation NSArrayMapProxy: NSProxy 
-  (instancetype) initWithArray: (NSArray*) anArray {
    array = anArray;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
    for (id obj in array) {
        if ([obj respondsToSelector:sel]) {
            return [obj methodSignatureForSelector:sel];
        }
    }
    return [super methodSignatureForSelector:sel];
}
- (void)forwardInvocation:(NSInvocation *)invocation {
    SEL selector = [invocation selector];
    NSMutableArray* mutableArray = [NSMutableArray arrayWithCapacity:[array count]];
    for (id obj in array) {
        if ([obj respondsToSelector:selector]) {
            [invocation invokeWithTarget:obj];
            id mapped;
            [invocation getReturnValue:&mapped];
            [mutableArray addObject: mapped];
        }
    }
   // 重要,实质上这里是进入了C field,如果不手动retain的话,数组就会被自动释放了
    CFBridgingRetain(mutableArray);
    [invocation setReturnValue: &mutableArray];
}
@end