Я пытаюсь сохранить ссылку на блок, который был передан моему классу методом, для вызова позднее. Однако у меня возникают проблемы с поддержанием ссылки на него.
Очевидным способом, я думал, было добавить его в коллекцию ivar, и все они должны поддерживать сильные ссылки на их содержимое. Но когда я пытаюсь вытащить его обратно, это нуль.
Код довольно прост:
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 хранится блок? Имеет ли это отношение к тому, что я нацелен на iOS 4.3, и поэтому ARC должен быть встроен в статическую библиотеку?
Обновление 3: Дамы и господа: я идиот.
Код, представленный здесь, был явно упрощенной версией фактического кода; в частности, он оставлял некоторые пары ключ/значение из словаря.
Если вы сохраняете значение в NSDictionary с помощью [NSDictionary dictionaryWithObjectsAndKeys:]
, вам лучше быть уверенным, что одно из этих значений не nil
.
Один из них был.
ICYMI, это привело к досрочному прекращению списка аргументов. У меня был аргумент userInfo-типа, передаваемый в один из методов "добавить в очередь", и вы, конечно, могли бы пройти "nil". Затем, когда я построил словарь, в этом аргументе заставило конструктор думать, что я завершил список аргументов. @"callback"
было последним значением в конструкторе словаря и никогда не сохранялось.