Я пытаюсь сохранить ссылку на блок, который был передан моему классу методом, чтобы вызвать его позже. Однако у меня возникли проблемы с сохранением ссылки на него.
Я подумал, что очевидным способом было бы добавить его в коллекцию 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"
было последним значением в конструкторе словаря, и оно никогда не сохранялось.
functionToBeCalledLater
возникает на другой итерации цикла выполнения, хотя я не думаю, что это имеет значение, но, возможно, это как-то связано с тем, где ARC размещает свои удержания и выпуски. - person Morgan Harris   schedule 14.11.2011