我有一个objective-c对象,我将其传递给其构造函数。这是一个特殊情况,我想在视图控制器完全加载时发射该块。但是,在该块中,我还想引用我将块传递到的对象。考虑此示例:
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
)。有什么方法可以实现这一目标吗?我确实知道解决我的特定问题的解决方案和模式,但是我想知道是否可以参考。
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);
如果在创建以下实例之前,请简单地将对象设置为nil
,则应照顾您的警告。
__block TestClass *obj = nil;
obj = [[TestClass alloc] initMyObjectWithBlock:^{
[obj doSomething];
}];
关于对象,它确实退出,因为您没有在initMyObjectWithBlock
初始化器中调用块。
尽管上述代码有效,但正如乔什(Josh)所提到的,有一个保留周期。为了解决保留周期,您可以做类似的事情:
TestClass *obj = nil;
__block __weak TestClass *objWeak = nil;
obj = [[TestClass alloc] initMyObjectWithBlock:^{
TestClass *newObj = objWeak;
[newObj doSomething];
}];
objWeak = obj;
您只是创建一个虚拟变量以传递到块。
这是CY-4AH答案的补充。长期以来要发表评论。
首先:跑入"工作环境"是一种代码气味。可能有两个原因:
a。MyObject
是两个不同任务的共生:1。发生$发生的事情。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
垃圾来解决概念问题。