在块中引用self传递给构造函数

时间:2014-03-08 23:34:49

标签: objective-c objective-c-blocks variable-initialization

我有一个Objective-C对象,我将一个Block传递给它的构造函数。这是一个特殊情况,我想在视图控制器完全加载时触发该块。但是,在那个Block中我还想引用我传递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]行,我得到“当被块捕获时,变量未初始化”警告,这是有道理的。在那个Block中,我需要一个对“父”对象的引用(在这种情况下为obj)。有没有办法实现这个目标?我确实知道我的具体问题的解决方法和模式,但我想知道这样的引用是否可行。

3 个答案:

答案 0 :(得分: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);

答案 1 :(得分:0)

如果您在创建实例之前将对象设置为nil,则应该注意您的警告。

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

关于object,它会退出,因为你没有在initMyObjectWithBlock初始化程序中调用阻塞。

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

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

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

    [newObj doSomething];
}];

objWeak = obj;

您只是创建一个虚拟变量以传入您的块。

答案 2 :(得分:0)

这是对Cy-4AH答案的补充。很快就把它写进了评论。

首先:遇到“解决方法”是一种代码气味。可能有两个原因:

一个。 MyObject是两个不同任务的共生:1。火,当$ $发生时。 2.在解雇时做一些事情。将MyObject分解为MyObject1MyObject2可能有所帮助。但当然我们需要更多信息。

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垃圾来涵盖概念问题。