如果我有一个Objective-C方法接受一个object参数,并且所述方法使用一个块在内部完成它的工作,有没有办法从块中修改该对象?
据我所知,块通过在块中引用变量来捕获变量,并且默认情况下会复制它们。如果我想能够修改而不是使用周围对象的副本,我可以用__block
作为声明的前缀,但我不能用方法参数这样做,因为我没有声明它我自己,对吧?
例如:
- (void)doWorkWithString:(NSString *)someString
{
[NSFoo doAwesomeClassMethodWithBlock:^{
// How can I modify someString here directly?
// By just changing someString, I'm changing the captured copy
}];
}
答案 0 :(得分:2)
“采用对象参数”
首先,您几乎肯定会因为您不能拥有对象类型的参数或变量而感到困惑。您只能指向对象。所以,是的,块阻止了块捕获的非__block
变量。但这里的变量是基元或对象指针,而不是“对象”。
如果您只需要改变对象指针所指向的对象,并且不涉及将指针更改为指向另一个对象,那么您不会更改该变量。由于您没有更改变量,所有这些“复制变量”和__block
内容完全无关。
答案 1 :(得分:1)
你对捕获的看法是正确的;您可能想要做的是提供应该作为块的主题的对象作为它的参数 - 就像您调用C函数一样。例如,
void (^ someBlock)(NSString *) =
^(NSString *someString)
{
NSLog(@"length is %d", [someString length]);
};
...
someBlock(@"String 1");
someBlock(@"A second string");
答案 2 :(得分:1)
我意识到上面的评论令人难以置信的混乱。希望以下内容清除了我想说的内容:
- (void)yourMethod:(Foo *)parameterFoo
{
__block Foo *blockVariable = [Foo someFoo];
Foo *capturedVariable = [Foo anotherFoo];
void(^doWorkBlock)(Foo *bp) = ^(Foo *bp){
// If your block accesses a scoped variable that is not marked with __block, it will
// retain it, so here capturedVariable and bp would be retained by the block
capturedVariable.aProperty = 5.0;
bp.aProperty = 10.0;
// As you can see, you can modify the objects all you like.
// What you cannot do is assign something to capturedVariable or bp because they
// were not marked as __block
// WONT WORK
capturedVariable = [Foo new];
// However, you can write to blockVariable because it is marked as __block
// WORKS
blockVariable = [Foo new];
// Remember, though that the block will not retain this variable itself because
// of the __block
};
// Note, it's weird for the block to take a parameter since it could just access the
// variable directly. This just serves to show how a block would handle a parameter.
doWorkBlock(parameterFoo);
}