通过弱指针分配给块中的ivar [英] Assignment to ivar in a Block via weak pointer

查看:83
本文介绍了通过弱指针分配给块中的ivar的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的界面文件中有一个只读属性isFinished:

I have a read-only property isFinished in my interface file:

typedef void (^MyFinishedBlock)(BOOL success, NSError *e);

@interface TMSyncBase : NSObject {
     BOOL isFinished_;
}

@property (nonatomic, readonly) BOOL isFinished;

,我想稍后在某个块中将其设置为YES,而不创建对self的保留周期:

and I want to set it to YES in a block at some point later, without creating a retain cycle to self:

- (void)doSomethingWithFinishedBlock:(MyFinishedBlock)theFinishedBlock {
    __weak MyClass *weakSelf = self;
    MyFinishedBlock finishedBlockWrapper = ^(BOOL success, NSError *e) {
        [weakSelf willChangeValueForKey:@"isFinished"];
        weakSelf -> isFinished_ = YES;
        [weakSelf didChangeValueForKey:@"isFinished"];
        theFinishedBlock(success, e);
    };

    self.finishedBlock = finishedBlockWrapper; // finishedBlock is a class ext. property
}

我不确定这是正确的方法.该代码会泄漏,破坏还是正常?也许有一种更容易被我忽略的方法?

I'm unsure that this is the right way to do it. Will this code leak, or break, or is it fine? Perhaps there is an easier way I have overlooked?

推荐答案

传递的块变量可以为nil,请在调用之前进行检查,或者在函数启动时添加断言,否则您将崩溃

Passing block variable can be nil, check before calling or add assert on start of the function or you will crash

由于您没有保留self,因此我们假设您在代码被执行的时候在后台线程上执行了一些长任务softSelf可以为nil(希望您使用的是ARC和5.0,所以您对弱引用进行了限制).

Since you are not retaining self and we assume that you execute some long task on background thread by the time your code get's executed weakSelf can be nil ( hopefully you are using ARC and 5.0 so you have niled weak references ).

如果您没有真正的弱引用(<5.0,没有ARC,编译器仍会接受__weak,但这无关紧要),这将导致崩溃.

If you don't have real weak references ( < 5.0, no ARC, compiler would still accept __weak but it wouldn't matter ) this would lead to crash.

如果对象指针为零,则使用'->'访问ivar也会导致崩溃,因此您需要确保不会发生这种情况.

Also accessing ivar using '->' will lead to crash if object pointer is nil so you need to make sure it doesn't happen.

即使您按照dasblinkenlight编写的代码运行,如果此时softSelf将为nil,它也可能崩溃,假设您在后台线程上分派了块,然后在块执行之前释放了对象,这使weakSelf为零,因此可以通过以下方式对其进行访问:使用->"将导致崩溃.在那种情况下,我将修改代码如下:

Even if you do the code as dasblinkenlight wrote it can crash if weakSelf will be nil at the moment, let's say you dispatch the block on background thread and then object get released before block's executes, this makes weakSelf nil thus accesing it by using '->' will lead to crash. In that case I would modify the code as follows:

__weak MyClass *weakSelf = self;
MyFinishedBlock finishedBlockWrapper = ^(BOOL success, NSError *e) {
    MyClass *strongSelf = weakSelf;
    //! whatever task you want executed
    strongSelf.isFinished = YES;
    theFinishedBlock(success, e);
};

此外,您还可以测试weakSelf是否为nil,以防止昂贵的任务在没有意义的情况下执行(对象已被破坏).但这取决于用例.

Also you could test if weakSelf is nil to prevent expensive task from execution if it doesn't make sense ( object is already destroyed ). But this depends on use case.

但是在使用块编程时,还需要考虑其他情况,例如: 您可以有一个作业对象实例,其唯一作用是在后台执行某些任务,在这种情况下,此代码可能会失败,因为您将创建新任务,并且可以在后台线程上执行块之前将其释放,在这种情况下,您应保留self并且不要在对象中保留块(这将防止保留周期).

But there is also other case you need to consider when programming with blocks, for example: You can have a job object instance that's only role is to execute some task in background, in that case this code could fail because you would create new task and it could be deallocated before block executes on background thread, in that case you should retain self and don't retain block in the object ( this will prevent retain cycle ).

这篇关于通过弱指针分配给块中的ivar的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆