NSTimer类别+阻止实现替换选择器 [英] NSTimer Category + Blocks implementation to replace selector

查看:181
本文介绍了NSTimer类别+阻止实现替换选择器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆