我对块和 objective-c很新,我试图用两者写我的第一个类别.我的想法是在NSTimer上创建一个类别,它将接收一个块作为参数,这个块将用于选择器调用.现在我有这个. // NSTimer+Additions.h#import F
// NSTimer+Additions.h #import <Foundation/Foundation.h> typedef void (^VoidBlock)(); @interface NSTimer (NSTimer_Additions) + (NSTimer *)scheduleTimerWithTimeInterval:(NSTimeInterval)theSeconds repeats:(BOOL)repeats actions:(VoidBlock)actions; @end #import "NSTimer+Additions.h" static VoidBlock _voidBlock; @interface NSTimer (AdditionsPrivate) // Private stuff - (void)theBlock; @end @implementation NSTimer (NSTimer_Additions) + (NSTimer *)scheduleTimerWithTimeInterval:(NSTimeInterval)theSeconds repeats:(BOOL)repeats actions:(VoidBlock)actions { [_voidBlock release]; _voidBlock = [actions copy]; NSTimer* timer = [[NSTimer alloc] initWithFireDate:[NSDate date] interval:theSeconds target:self selector:@selector(theBlock) userInfo:nil repeats:repeats]; [timer fire]; return [timer autorelease]; } - (void)theBlock { _voidBlock(); } @end
代码要点:https://gist.github.com/1065235
一切都编译好但我有以下错误:
2011-07-05 14:35:47.068 TesteTimer [37716:903] *由于未捕获的异常’NSInvalidArgumentException’终止应用程序,原因:'[NSTimer theBlock]:无法识别的选择器发送到类0x7fff70bb0a18′
我该如何使这个类别工作?
除了错误的目标之外,你的主要缺陷是你使用静态变量.除了一个计时器,你将无法支持.使用block作为被调用方法的参数.
@interface NSTimer (AdditionsPrivate) // Private stuff - (void)theBlock:(VoidBlock)voidBlock; @end @implementation NSTimer (NSTimer_Additions) + (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)theSeconds repeats:(BOOL)repeats actions:(VoidBlock)actions { NSInvocation * invocation = [NSInvocation invocationWithMethodSignature:[self instanceMethodSignatureForSelector:@selector(theBlock:)]]; NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval:theSeconds invocation:invocation repeats:repeats]; [invocation setTarget:timer]; [invocation setSelector:@selector(theBlock:)]; Block_copy(actions); [invocation setArgument:&actions atIndex:2]; Block_release(actions); return timer; } - (void)theBlock:(VoidBlock)voidBlock { voidBlock(); } @end
使用关联引用的问题是泄漏,因为释放块没有好处.
早期的方法使用关联参考
您可以使用associative references
将块附加到该特定NSTimer实例.
@implementation NSTimer (NSTimer_Additions) + (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)theSeconds repeats:(BOOL)repeats actions:(VoidBlock)actions { NSInvocation * invocation = [NSInvocation invocationWithMethodSignature:[self instanceMethodSignatureForSelector:@selector(theBlock)]]; NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval:theSeconds invocation:invocation repeats:repeats]; [invocation setTarget:timer]; [invocation setSelector:@selector(theBlock)]; objc_setAssociatedObject(timer, @"Block", actions, OBJC_ASSOCIATION_COPY); return timer; } - (void)theBlock { VoidBlock _voidBlock = (VoidBlock)objc_getAssociatedObject(self, @"Block"); _voidBlock(); } @end