在std :: function中存储objective-c块是否安全?

时间:2018-02-04 23:15:56

标签: objective-c++ clang++

我想将一个回调块从我的Objective-C ++代码传递给C ++对象。它非常简单,因为我能够将块分配给std :: function。在我的迷你示例中,一切正常,但我仍然不确定这样做是否安全。

#import "ViewController.h"
#include <functional>

std::function<void(void)> f;


@interface T : NSObject
@property (strong) NSString* value;
@end

@implementation T
- (void)dealloc {
    NSLog(@"dealloc");
}
@end


@implementation ViewController


- (IBAction)storeBlock:(UIButton *)sender {
    T* t = [[T alloc] init];
    t.value = @"the captured obj";
    f = ^void(void) { NSLog(@"This is the block with %@", t.value); };
}

- (IBAction)useBlock:(UIButton *)sender {
    f();
}

- (IBAction)releaseBlock:(UIButton *)sender {
    f = nullptr;
}


@end

我已经知道这些块存储在堆栈中,如果我想进一步使用它,我必须将它复制到堆中,而不是创建块的范围(我没有&#39) ;在我的例子中明确地完成了)。我也不确定ARC如何处理这种情况。是官方的吗?允许这样做?我正在使用Xcode 9.2。

2 个答案:

答案 0 :(得分:0)

当执行离开定义块的范围时,Objective-C块变为无效。为避免这种情况,必须在块上使用复制方法,即全部。

答案 1 :(得分:0)

块被视为普通对象,尽管它们在堆栈上开始它们的生命周期。就像你说的,在objc-cpp中我们可以很容易地在std :: function中存储一个块: - )

那么你的例子会发生什么? 您将std :: function“f”声明为全局堆栈对象。当块被分配给它时,块对象的引用计数为1.你的“T”对象在storeBlock函数中有两个引用之前。一个通过“t”,一个通过块的捕获机制。离开范围,只剩下块参考。 然后将“f”设置为nullptr:没有对块对象的引用 - &gt;该块被取消分配并带有“T”对象,因为它既没有指向它的引用。