我对块和 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
