简体   繁体   English

__weak self可以在块的中间变成零吗?

[英]Can __weak self turn nil in the middle of the block?

When using a __weak self reference in my block that runs on a background thread, do I only need to check for nil in the beginning, or can the __weak self become nil even during execution after the first nil test has passed? 当在后台线程上运行的块中使用__weak self引用时,我是否仅需要在开始时检查nil ,或者即使在第一个nil测试通过后执行期间__weak self也可以变为nil? I want to access some ivars from self in the block and I need the latest values at the time the block is executing. 我想从代码块中的self访问一些ivars,并且在代码块执行时需要最新的值。

If no one is holding a reference to self then yes. 如果没有人提到self那就是。 You can mitigate this by taking a strong reference in the block 您可以通过在代码块中充分引用来减轻这种情况

__weak __typeof(self) weakSelf = self;

^{
  __strong __typeof(weakSelf) strongSelf = weakSelf;
  if (!strongSelf) {
    return;
  }
};

You can avoid having your reference set to nil by strongly referencing it from inside the block. 通过从块内部强烈引用,可以避免将引用设置为nil。

Get a strong reference to your weak pointer inside the block. 强烈引用块内的弱指针。

__weak MyObject *weakSelf = self; // a weak reference
myBlock = ^{
  MyObject *innerSelf = weakSelf; // a block-local strong reference
  NSLog(@"MyObject: %@", innerSelf); 
};

Avoid using the variables directly, because it will cause retain cycles. 避免直接使用变量,因为这会导致保留周期。 If you use an instance variable directly within a block, the block will capture self so you'll have to reference the instance variables using their accessors. 如果直接在块内使用实例变量,则该块将捕获self,因此您必须使用其访问器来引用实例变量。

__weak MyObject *weakSelf = self;
myBlock = ^{
    MyObject *innerSelf = weakSelf; // a block-local strong reference
    NSLog(@"MyObject: %@", innerSelf);
    NSLog(@"MyObject ID: %d", innerSelf.objectID);
};

If you use the instance variables directly like this: 如果您像这样直接使用实例变量:

NSLog(@"MyObject ID: %d", _objectID);

The compiler interprets _objectID as self->_objectID , where self is captured by your block. 编译器将_objectID解释为self->_objectID ,其中self被您的块捕获。

It is in the nature of a weak reference that it can become nil at any time, when the last strong reference is removed in another thread. 弱引用的本质是,当在另一个线程中删除最后一个强引用时,它随时可能变为零。 This is fatal if you access member variables because you will crash, and it is fatal if you call a method on that weak variable, since self is unsafe unretained. 如果您访问成员变量,这将是致命的,因为这将导致崩溃;而如果对该弱变量调用方法,则将是致命的,因为self是不安全的,无法保留。

There is a trivial way to fix this which everyone uses: Store the weak variable into a string one before doing anything, without any checks. 每个人都可以使用一种简单的方法来解决此问题:在执行任何操作之前,不做任何检查就将弱变量存储到字符串中。 Then you check whether the strong variable is nil; 然后检查强变量是否为nil; that check is needed once . 那检查需要一次

Turn all warnings on in Xcode, so you will get a warning if you do anything dangerous. 在Xcode中打开所有警告,因此,如果您做任何危险的事情,都会收到警告。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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