弱引用自身是否必要(performSelector)

3

我有一个NSObject分类,可以在一定时间间隔后执行代码块。那么我需要在这种情况下使用weak self吗?

    __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();
}

1
为什么不使用dispatch_after呢? - ChrisH
之前一直在使用 dispatch_after,但是在 IOS7 上,短时间间隔的精度非常差。我发现设置 dispatch_after 0.3 秒时,实际执行时间可能会相差30%左右。 - BlackMouse
2个回答

6

如果您在代码中包含它,很可能会引入严重的错误,而且您实际上并不需要它(self没有对块的强引用,所以没有循环)。特别是,没有任何东西可以防止块运行之前'self'被释放(因为弱引用的整个目的就是不阻止事物被释放)。


2
我对“可能引入严重的错误”并不确定。如果没有其他东西保留视图控制器,您可能不想将其保留以在延迟后运行某些内容。我曾经看到过由于某些东西没有使用弱引用而导致视图控制器被保留的时间比您预期的要长而导致的错误。 - Jesse Rusak
4
没有使用weak关键字时,代码是正确的。使用weak关键字后,后果不明(可能是无害的,这取决于代码)。最好让一个视图控制器绕一圈半秒钟,了解代码的作用。使用weak可以避免循环引用的问题,但同时也会让系统在你不知情的情况下撤销你的变量引用。 - Jano

3

补充一下@Catfish_Man的描述:

在块之前可以使self变弱,然后在块内部可以再次使其变强,以确保它不会在意外时间被释放。在这种情况下,应确保在self被释放后不执行块。这很难,因此只要没有创建循环(如果self持有对块的引用,则会创建循环),保持其强引用是较安全的选择

提示:如果您开始考虑信号而不是过程顺序,那么使用Reactive Cocoa的最终结果可能更令人满意:

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];

乍一看可能有点晦涩,但信号可以让你的生活变得更加轻松。特别是因为如果信号与自身的生命周期相关联,例如它是一个属性,当自身被释放时,它将被释放,从而确保块在不需要执行时不会被执行。在这种情况下,需要进行弱化和强化。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接