简体   繁体   中英

Is weak self necessary (performSelector)

I have a NSObject category to execute blocks after some interval. Do I need to weak self in this instance?

    __weak ViewController *weakSelf = self; 
   [self runBlockAfterDelay:0.6 block:^{

        weakSelf.someview = ...
    }];




 // Category 

- (void)runBlockAfterDelay:(NSTimeInterval)delay block:(void (^)(void))block {

    dispatch_async(dispatch_get_main_queue(), ^{

        [self performSelector:@selector(executeBlockAfterDelay:) withObject:[block copy] afterDelay:delay];
    });
}

- (void)executeBlockAfterDelay:(void(^)(void))block
{
    if (block)
        block();
}

Not only do you not need it (self does not have a strong reference to the block, so there's no cycle), it will likely introduce serious bugs into your program if you include it. Specifically, nothing will prevent 'self' from being deallocated before the block runs (since the whole point of a weak reference is that it doesn't prevent things from being deallocated).

Just to add a little more detail to @Catfish_Man's great description:

You can weakify self before the block and inside the block you can strongify it again to make sure it is not released in an unexpected time. In this case it should be ensured that the block is not executed after self has been released. This is hard, so leaving it strong is a safer option as long as no cycles are created . (Cycle would be created if self held a reference to the block.)

FYI: If you start thinking in terms of signals instead of procedural ordering, the final result with Reactive Cocoa can be more pleasing:

NSTimeInterval delay = 0.3;
// The activator signal that fires after the delay and completes after it.
RACSignal *delayedActivator = [[RACSignal interval:delay] take:1];

@weakify(self)
// The command that we want to execute after the delay.
RACCommand *blockToExecute = [RACCommand command];
[blockToExecute addSignalBlock:^RACSignal *(id value) {
    @strongify(self)
    self.whatever
}];

// Wire up the command on the signal.
[delayedActivator executeCommand:blockToExecute];

May look a little cryptic at first sight but signals can make your life a whole lot easier. Especially because if the signal is tied to the life cycle of self, eg it is a property, it will be released when self is released, this way ensuring that the block is not executed when not needed. In this case the weakification and strongification are required.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM