it-swarm.com.ru

Сохранить селектор как значение в NSDictionary

Есть ли способ сохранить селектор в NSDictionary, не сохраняя его как NSString?

52
synic

SEL - это просто указатель, который вы можете сохранить в NSValue:

NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: 
                       [NSValue valueWithPointer:@selector(foo)], @"foo",
                       nil];

Чтобы вернуть селектор, вы можете использовать:

SEL aSel = [[dict objectForKey:@"foo"] pointerValue];
104
Georg Fritzsche

Альтернативой решению Георга было бы преобразовать селектор в строку NSString перед сохранением NSDictionary:

NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: 
                      NSStringFromSelector(@selector(foo)), @"foo",
                      nil];

SEL selector = NSSelectorFromString([dict objectForKey:@"foo"]);

Этот метод, хотя и использует больше памяти, дает вам возможность сериализовать весь NSDictionary в виде строки через библиотеки, такие как JSONKit.

10
David H

NSDictionary на самом деле просто CFDictionary, который сохраняет и освобождает все ключи и значения. Если вы создаете CFDictionary напрямую, вы можете настроить его так, чтобы он не сохранял и не сбрасывал значения. Вы можете ввести CFDictionaryRef в NSDictionary * и наоборот.

6
drawnonward

В случае использования UILocalNotification единственным способом является использование NSSelectorFromString([dict objectForKey:@"foo"]). При valueWithPointer происходит сбой приложения при установке свойства userInfo объекта UILocalNotification. Быть осторожен.

3
kostas

Хотя ответ Георга должно работать, NSValue также поддерживает кодирование любого значения с использованием строки кодирования типа Objective-C, которая имеет специальный способ представления SEL— с помощью ":" (в отличие от "^v", создаваемого -valueWithPointer:, который переводится в void *) .
source: Руководство по программированию в Objective-C Runtime - Типовые кодировки

Если исходить из решения Георга, лучшим API-совместимым способом помещения SEL в NSValue в NSDictionary будет:

// store
NSDictionary *dict = @{
    @"foo": [NSValue value:&@selector(foo) withObjCType:@encode(SEL)]
};

// retrieve
SEL aSel;
[dict[@"foo"] getValue:&aSel];



Логическое обоснование для обработки SEL как его собственного зверя заключается в том, что документы описывают его как "непрозрачный тип", что означает, что его внутренняя работа (даже то, к чему он typedefd) запрещена для программистов приложений; Apple может смешать это в любое время в будущем.

Кроме того, использование void *s, чтобы заставить систему делать то, что вы хотите, было полезно в C еще в 90-х годах, когда большинство из нас не знали ничего лучшего. Теперь ты лучше.

Вышеупомянутый подход следует использовать только в том случае, если получение SEL происходит во время работы программы - вы не должны сохранять это NSDictionary на диск. Если вам нужно хранить долгосрочные SELs (при каждом запуске приложения), вы должны следовать подход Дэвида Х и преобразовать его в NSString.

2
Slipp D. Thompson