Сохранить селектор как значение в NSDictionary - PullRequest
52 голосов
/ 13 мая 2010

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

Ответы [ 5 ]

104 голосов
/ 13 мая 2010

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

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

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

SEL aSel = [[dict objectForKey:@"foo"] pointerValue];
10 голосов
/ 13 февраля 2012

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

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

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

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

6 голосов
/ 13 мая 2010

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

3 голосов
/ 22 мая 2012

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

2 голосов
/ 27 мая 2016

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

Отработка решения Georg, лучший API-совместимый способ поместить SEL в NSValue в NSDictionary, будет:

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

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


Обоснование для обработки SEL как своего собственного зверя заключается в том, что документы описывают его как «непрозрачный тип», что означает, что его внутренняя работа (даже то, что typedef d)закрыты для программистов приложений;Apple может перепутать это в любое время в будущем.

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

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

...