2

我有一个 Objective-C 对象,我将一个 Block 传递给它的构造函数。这是一个特殊情况,当它完全加载时,我想在视图控制器中触发该块。但是,在该块中,我还想引用我将块传递到的对象。考虑这个例子:

typedef void (^MyBlock)();

//constructor of my object
-(id)initMyObjectWithBlock:(MyBlock)block{
    self = [super init];
    if(self){
        myivar = block; //to be used later
    }
}

//somewhere else in my app
MyObject *obj = [[MyObject alloc] initMyObjectWithBlock:^{
   [obj doSomething];
}];

在那一[obj doSomething]行,我收到“变量在被块捕获时未初始化”警告,这是有道理的。在那个块中,我需要一个对“父”对象的引用(obj在这种情况下)。有什么办法可以做到这一点?我确实知道我的具体问题的解决方法和模式,但我想知道这样的参考是否可能。

4

3 回答 3

3
typedef void (^MyBlock)(MyObject*);

//constructor of my object
-(id)initMyObjectWithBlock:(MyBlock)block{
    self = [super init];
    if(self){
        myivar = block;
    }
}

//somewhere else in app
MyObject *obj = [[MyObject alloc] initMyObjectWithBlock:^(MyObject* myObj){
   [myObj doSomething];
}];

//and somewhere else in app
obj.myivar(obj);
于 2014-03-09T00:49:34.613 回答
0

如果您只是nil在创建实例之前将对象设置为,如下所示,它应该会处理您的警告。

__block TestClass *obj = nil;
obj = [[TestClass alloc] initMyObjectWithBlock:^{
    [obj doSomething];
}];

关于对象,它确实退出,因为您没有在initMyObjectWithBlock初始化程序中调用块。

虽然上面的代码有效,但正如乔希所说,有一个保留周期。要绕过保留周期,您可以执行以下操作:

TestClass *obj = nil;
__block __weak TestClass *objWeak = nil;

obj = [[TestClass alloc] initMyObjectWithBlock:^{
    TestClass *newObj = objWeak;

    [newObj doSomething];
}];

objWeak = obj;

您只是在其中创建一个虚拟变量以传递给您的块。

于 2014-03-09T00:15:18.033 回答
0

这是对 Cy-4AH 答案的补充。将其放入评论中太长了。

首先:遇到“变通办法”是一种代码味道。可能有两个原因:

A.MyObject是两个不同任务的共生: 1. 火灾,当 $something 发生时。2. 对 1) 触发时做某事。闯入MyObject并可以MyObject1提供MyObject2帮助。但我们当然需要更多信息。

B. 很多时候,当一个物体开火时,这个物体应该会发生一些事情,这是概念的一部分。(获取更多信息,更改状态,......)在这种情况下,模式非常简单:传递self给块:

来自 Cy-4AH:

typedef void (^MyBlock)(MyObject*);

//constructor of my object
-(id)initMyObjectWithBlock:(MyBlock)block{
    self = [super init];
    if(self){
        myivar = block;
    }
    return self; // Added this line for obvious reasons
}

//somewhere else in app
MyObject *obj = [[MyObject alloc] initMyObjectWithBlock:^(MyObject* myObj){
   [myObj doSomething];
}];

现在稍微改变一下:

在内部MyObject,当它调用块时

self.myivar( self );

正如 Cy-4AH 所说,你不需要所有的__block __unsafe_unretained __weak垃圾来解决概念问题。

于 2014-03-09T11:39:32.443 回答