NSTimer类别+阻止实现替换选择器 [英] NSTimer Category + Blocks implementation to replace selector
问题描述
我对块和objective-c很新,我正在尝试用两者编写我的第一个类别。我的想法是在NSTimer上创建一个类别,它将接收一个块作为参数,这个块将用于选择器调用。现在我有这个。
I am quite new to blocks and objective-c, and i am trying to write my first category using both. My idea is to create a category on NSTimer that will receive a block as a parameter and this block will be used in the selector call. Right now I have this.
// 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
代码的要点:< a href =https://gist.github.com/1065235\"rel =nofollow> https://gist.github.com/1065235
一切都编译好但我有以下错误:
Everything compiles fine but i have the following error:
2011-07-05 14:35:47.068 TesteTimer [37716:903] * 由于未捕获的异常'NSInvalidArgumentException'终止应用程序,原因:'+ [NSTimer theBlock]:无法识别的选择器发送到类0x7fff70bb0a18'
2011-07-05 14:35:47.068 TesteTimer[37716:903] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[NSTimer theBlock]: unrecognized selector sent to class 0x7fff70bb0a18'
如何使此类别有效?
推荐答案
除了错误的目标之外,你的主要缺陷是使用静态变量。除了单个计时器之外,您将无法支持。
Your major flaw besides the wrong target is your use of a static variable. You won't be able to support beyond a single timer.
@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
使用关联参考的问题泄漏是因为没有好处释放该区块。
The problem with using associative references was the leak as there was no good point to release the block.
您可以使用 关联引用
将块附加到的特定实例的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
这篇关于NSTimer类别+阻止实现替换选择器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!