NSTimer с блоком - я правильно делаю? - PullRequest
12 голосов
/ 23 февраля 2012

Ниже приведена моя категория Objective-C на NSTimer для выполнения блочного запуска NSTimer.Я не вижу в этом ничего плохого, но я получаю то, что блок, который я передаю в метод 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

Ответы [ 5 ]

32 голосов
/ 17 июля 2014

Я нашел этот код в 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
];
8 голосов
/ 22 апреля 2013

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

Cocoapod BlocksKit , позволяющий блокировать группу классов ...

#import "NSTimer+BlocksKit.h"
[NSTimer bk_scheduledTimerWithTimeInterval:1.0 block:^(NSTimer *time) {
       // your code
    } repeats:YES];
3 голосов
/ 31 января 2016

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

NSTimer.scheduledTimerWithTimeInterval(0.7, target: NSBlockOperation(block: {
    /* do work */
}), selector: "main", userInfo: nil, repeats: false)
2 голосов
/ 13 ноября 2012

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

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

0 голосов
/ 23 февраля 2012

попробуйте

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
...