Ios 强制对象生存直到执行块的正确方法
我正在使用自动参考计数。 我希望对象一直存在,直到执行某个回调:Ios 强制对象生存直到执行块的正确方法,ios,objective-c,objective-c-blocks,Ios,Objective C,Objective C Blocks,我正在使用自动参考计数。 我希望对象一直存在,直到执行某个回调: Foo *obj = [[Foo alloc] init]; [obj someMethod: @"AAA", ^(NSError * _Nullable error) { //callback }); 我需要obj在调用“callback”之前一直处于活动状态, 但我实际上并没有在回调中使用它。 现在,我用以下方法“解决”它: 但这看起来很奇怪。这种情况可能有一些语言结构, 或者除了打印到日
Foo *obj = [[Foo alloc] init];
[obj someMethod: @"AAA", ^(NSError * _Nullable error) {
//callback
});
我需要obj
在调用“callback”之前一直处于活动状态,
但我实际上并没有在回调中使用它。
现在,我用以下方法“解决”它:
但这看起来很奇怪。这种情况可能有一些语言结构,
或者除了打印到日志之外,还有一些典型的解决方法?如果在块内使用外部变量
obj
,则其值将捕获到块中。这将创建对对象的附加引用,以便自动引用计数使其保持活动状态,直到执行块为止
要保留该引用,不需要将其传递给另一个函数,如NSLog()
。只需将其存储在局部变量中就足够了
Foo *obj = [[Foo alloc] init];
[obj someMethod: @"AAA", ^(NSError * _Nullable error) {
Foo* keepObj = obj; // keeps obj alive
//callback
});
编辑:skaak反馈后改进的解决方案:
不需要未使用的局部变量名,您可以通过转换为void
来表示意图
Foo *obj = [[Foo alloc] init];
[obj someMethod: @"AAA", ^(NSError * _Nullable error) {
//callback
(void) obj; // release reference that kept obj alive
});
要手动管理对象的生命周期,您可以通过在块内设置
nil
来捕获它,例如:
__block Foo *obj = [Foo new];
[obj someMethod:@"AAA" block:^(NSError * _Nullable error) {
NSLog(@"start block");
...
obj = nil;
NSLog(@"end block");
}];
NSLog(@"finish");
Prints:
start block
Foo dealloc
end block
finish
@马特没有帮助,调用
someMethod
和调用callbackobj
之间有足够长的延迟,无论我如何定义它\uuuu block Foo*obj=
或者仅仅Foo*obj=
为什么需要它?@user1244932:声明\uu block Foo*obj如果obj
实际上未在块内引用,则code>不会更改行为。如果它被引用,则不需要使用\u block
来使obj
保持活动状态。我认为它只取决于Foo
类及其方法实现Foo
应在回调前保留selfcall@RomanPodymov因为程序不能正常工作,若Foo
对象会在调用回调之前被销毁,但这将是“未使用的变量”。因此,处于释放模式的编译器可以将其删除?在这种情况下,编译器无法优化该变量,因为它会产生副作用——特别是保留和释放对象引用。我测试了它:它保持不变。除此之外,警告“unused variable”告诉您,这种保持对象活动的方式不是很有表现力;你至少应该评论一下意图。@kish-我正在思考,你可以做obj代码>内部块。你也能测试一下吗?我肯定编译器会抱怨,但我想它会的。这整件事都是关于变量进出范围的。在Obj-C中,你可以用它做各种各样的好事,就像这个家伙所做的那样@skaak:是的,你的建议很有效。我喜欢它,因为它没有引入额外的局部变量名。你甚至可以做(void)obj
,这几乎写下了意图。@kisch-谢谢你测试它并给出反馈。。。我不会做void
的事情,那是为了那些不知道如何关闭编译器警告的人。。。谢谢,我看到你也更新了你的答案。
__block Foo *obj = [Foo new];
[obj someMethod:@"AAA" block:^(NSError * _Nullable error) {
NSLog(@"start block");
...
obj = nil;
NSLog(@"end block");
}];
NSLog(@"finish");
Prints:
start block
Foo dealloc
end block
finish