NSTimer с блоком - я делаю это правильно?

Ниже приведена моя категория Objective-C в NSTimer для блокировки NSTimers на основе блоков. Я не вижу ничего плохого в этом, но то, что я получаю, заключается в том, что блок, который я передаю в метод schedule..., освобождается, несмотря на то, что я нахожу его copy.

Что мне не хватает?

typedef void(^NSTimerFiredBlock)(NSTimer *timer);

@implementation NSTimer (MyExtension)

+ (void)timerFired:(NSTimer *)timer 
{
    NSTimerFiredBlock blk = timer.userInfo;
    if (blk != nil) {
        blk(timer);
    }
}

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds 
                                    repeats:(BOOL)repeats 
                                   callback:(NSTimerFiredBlock)blk 
{
    return [NSTimer scheduledTimerWithTimeInterval:seconds
                                            target:self
                                          selector:@selector(timerFired:)
                                          userInfo:[blk copy]
                                           repeats:repeats];
}

@end

Ответ 1

Я нашел этот код в http://orion98mc.blogspot.ca/2012/08/objective-c-blocks-for-fun.html

Отличная работа

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.7
      target:[NSBlockOperation blockOperationWithBlock:^{ /* do this! */ }]
      selector:@selector(main)
      userInfo:nil
      repeats:NO
];

Ответ 2

У вас есть проект по github, который выполняет эту работу!

Cocoapod BlocksKit, позволяет блокировать кучу классов...

#import "NSTimer+BlocksKit.h"
[NSTimer bk_scheduledTimerWithTimeInterval:1.0 block:^(NSTimer *time) {
       // your code
    } repeats:YES];

Ответ 3

То, что вам не хватает, заключается в том, что если блок, который вы проходите, находится в стеке, тогда copy будет делать то, что имя говорит, - это создаст копию блока над кучей. Поэтому вы не ожидаете изменений в поведении того, с которым вы проходили; никто не сохраняет его. Копия останется в живых, пока оригинал не освобожден.

(в остальном: если вы не используете ARC, вы также захотите автоповторить копию, вы должны передать ссылку без прав на userInfo:. В противном случае копия никогда не будет освобождена)

Ответ 4

Вот версия Swift Ответ Mc.Stever:

NSTimer.scheduledTimerWithTimeInterval(0.7, target: NSBlockOperation(block: {
    /* do work */
}), selector: "main", userInfo: nil, repeats: false)

Ответ 5

попробуйте это

typedef void(^NSTimerFiredBlock)(NSTimer *timer);

@interface NSObject (BlocksAdditions)

- (void)my_callBlock:(NSTimer *)timer;

@end

@implementation NSObject (BlocksAdditions)

- (void)my_callBlock:(NSTimer *)timer {
    NSTimerFiredBlock block = (id)self;
    block(timer);
}

@implementation NSTimer (MyExtension)

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds 
                                    repeats:(BOOL)repeats 
                                   callback:(NSTimerFiredBlock)blk 
{
    blk = [[blk copy] autorelease];
    return [NSTimer scheduledTimerWithTimeInterval:seconds
                                            target:blk
                                          selector:@selector(my_callBlock:)
                                          userInfo:nil
                                           repeats:repeats];
}

@end