【问题标题】:Is it safe to store an objective-c block in a std::function?将objective-c 块存储在std::function 中是否安全?
【发布时间】:2018-03-01 05:05:06
【问题描述】:

我想将一个回调块从我的 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

我了解到这些块存储在堆栈中,如果我想在块的创建范围之外进一步使用它,我必须将它复制到堆中(我在我的示例中没有明确地这样做) .我也不确定ARC如何处理这种情况。是否“官方”允许这样做?我正在使用 Xcode 9.2。

【问题讨论】:

    标签: objective-c++ clang++


    【解决方案1】:

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

    【讨论】:

    • 现在我了解到 ARC 会在将块分配给变量时插入 Block_copy 调用。这就是我的示例代码有效的原因,尽管我在创建范围之后使用了该块。然而,引用计数机制(涉及 std::function)对我来说仍然很神秘。是什么让区块被释放?
    【解决方案2】:

    块被视为普通对象,尽管它们的生命周期是在堆栈上开始的。正如你所说,在 objc-cpp 中,我们可以轻松地将块存储在 std::function 中:-)

    那么在您的示例中发生了什么? 您将 std::function "f" 声明为全局堆栈对象。当块被分配给它时,块对象的引用计数为 1。您的“T”对象在 storeBlock 函数中具有,然后在其上留下两个引用。一个通过“t”,一个通过块中的捕获机制。离开范围,只剩下块引用。 然后将“f”设置为 nullptr:没有对块对象的引用 -> 块被解除分配,而“T”对象也被释放,因为它也没有指向它的引用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-06-26
      • 1970-01-01
      • 2021-01-23
      • 1970-01-01
      • 2021-09-26
      • 1970-01-01
      • 2011-01-07
      相关资源
      最近更新 更多