我试图通过一个方法将传递给我的类的Block保留下来,以便稍后调用。然而,我遇到了问题,无法维护对它的引用。
我想到的显而易见的方法是将它添加到一个ivar集合中,所有这些集合都应该维护对其内容的强引用。但是当我尝试将其取回时,它为nil。
代码非常简单:
typedef void (^DataControllerCallback)(id rslt);
@interface DataController : NSObject {
NSMutableArray* queue;
}
- (void) addBlock:(DataControllerCallback)callback;
- (void) functionToBeCalledLater;
@end
@implementation DataController
- (id) init {
self = [super init];
if (self != nil) {
queue = [NSMutableArray new];
}
return self;
}
- (void) addBlock:(DataControllerCallback)callback {
NSDictionary* toAdd = [NSDictionary dictionaryWithObjectsAndKeys:
[callback copy], @"callback",
@"some other data", @"data", nil];
[queue addObject:toAdd];
}
- (void) functionToBeCalledLater {
NSDictionary* dict = [queue lastObject];
NSLog(@"%@", [dict objectForKey:@"data"]; //works
DataControllerCallback callback = [dict objectForKey:@"callback"]; //this is nil
callback(@"an arguemnt"); //EXC_BAD_ACCESS
}
发生了什么?
更新:我已经尝试了[callback copy]
和只插入callback
到字典中,两者都不起作用。
更新2:如果我将代码块放入NSMutableSet中,只要我调用copy
,就可以正常工作。它很棒。但是如果它在NSDictionary中,就不行。
我实际测试过了,在创建NSDict之后立即设置断点,回调函数从未被插入。描述清楚地显示“1个键值对”,而不是两个。
我目前正在使用一个专门的类来解决这个问题。 callback
属性被声明为strong; 我甚至不需要使用copy
。
然而,问题仍然存在:为什么会发生这种情况?为什么NSDictionary不会存储Block?这是否与我针对iOS 4.3并且ARC必须作为静态库构建有关?
更新3:女士们先生们:我是个白痴。
我在这里展示的代码显然是实际代码的简化版本; 尤其是,它省略了一些键/值对。
如果您使用[NSDictionary dictionaryWithObjectsAndKeys:]
将值存储在NSDictionary中,您最好确保这些值之一不是nil
。
其中一个是。
如果您错过了这一点,它会导致参数列表的提前终止。我有一个userInfo类型的参数传递到其中一个“添加到队列”的方法中,您当然可以传递“nil”。然后,当我构造字典并将该参数投入其中时,构造函数会认为我已经终止了参数列表。 @"callback"
是字典构造器中的最后一个值,它从未被存储。
functionToBeCalledLater
在运行循环的不同迭代中发生,尽管我认为这并不重要,但也许与 ARC 放置其保留和释放的位置有关。 - Morgan Harris