passing a block in @selector()

2019-07-23 19:41发布

问题:

How do I pass a block, and what would it look like, in the method incrementCount:completion to get the property self.count returned after its increment in the CounterClass? I'm not sure if the way I defined the block parameter (void(^)(void))callback; in the method is correct i.e. should it also have a return value?

ViewController

 [NSTimer scheduledTimerWithTimeInterval:3.0
                                         target:self.counterClass
                                       selector:@selector(incrementCount:completion:)
                                       userInfo:nil
                                        repeats:YES];

CounterClass

-(void)incrementCount:(NSTimer *)timer completion:(void(^)(void))callback;
    {
        self.count += 1;

    }

回答1:

NSTimer expects to call a method which takes zero or one parameters, if there is a parameter it should be the timer instance itself.

So, you can't have a method with 2 parameters where one is a block.

Instead, remove the second parameter and simply call another method or block in the method implementation. The block could be stored as an @property of the class.



回答2:

You can used dispatch_after.

ViewController:

[self.counterClass incrementCountWithCompletion:^{
        // Your block code
        NSLog(@"block code");
}];

CounterClass:

-(void)incrementCountWithCompletion:(void(^)(void))block;
{
    dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
    dispatch_queue_t queue = dispatch_get_main_queue(); // Choose whatever queue is approapriate to you
    //Beware of retain cycles and use weak self pattern appropriately 
    dispatch_after(delay, queue, ^{
        self.count += 1;        
        block();
        [self incrementCountWithCompletion:block];
    });
}


回答3:

You can add your block to the userInfo:

[NSTimer scheduledTimerWithTimeInterval:3.0 target:self.counterClass selector:@selector(incrementCount:) userInfo:@{@"completion" : [yourBlock copy]} repeats:YES];

CounterClass

- (void)incrementCount:(NSTimer *)timer {
    self.count += 1;
    void (^completion)(void) = timer.userInfo[@"completion"];
}

For more on storing a block in a dictionary: blocks in nsdictionary?