2011-01-12 1 views
5

В принципе, я следующий код (описано здесь: Objective-C Constants in Protocol)Objective-C Можно ли перезаписать [NSObject initialize]?

// MyProtocol.m 
const NSString *MYPROTOCOL_SIZE; 
const NSString *MYPROTOCOL_BOUNDS; 

@implementation NSObject(initializeConstantVariables) 

+(void) initialize { 
    if (self == [NSObject class]) 
    { 
     NSString **str = (NSString **)&MYPROTOCOL_SIZE; 
     *str = [[MyClass someStringLoadedFromAFile] stringByAppendingString:@"size"]; 
     str = (NSString **)&MYPROTOCOL_BOUNDS; 
     *str = [[MyClass someStringLoadedFromAFile] stringByAppendingString:@"bounds"]; 
    } 
} 

@end 

мне было интересно: Является ли это безопасно для меня, чтобы иметь категорию, которая подменяет +initialize метод в NSObject в?

+0

Во-первых, вам не нужно создавать категорию, для которой время выполнения вызовет вашу инициализацию, оно будет делать это автоматически до отправки любого сообщения. Во-вторых, что вы подразумеваете под «безопасностью»? Кто-нибудь читает документацию больше ??? –

+0

Посмотрите на категорию ... Это переписывание класса NSObject, а не моего класса. Я пытаюсь иметь метод, который, как я знаю, будет вызываться в начале любой программы, которая использует структуру, которую я создаю. –

ответ

14

Короче говоря, нет, вы не можете безопасно реализовать методы +initialize в категориях классов. Вы в конечном итоге замените существующую реализацию, если она есть, и если две категории одного класса реализуют +initialize, нет гарантии, которая будет выполнена.

+load имеет более предсказуемое и четко определенное поведение, но слишком рано делать что-либо полезное, потому что многие вещи находятся в неинициализированном состоянии.

Лично я пропускаю +load или +initialize в целом и использую аннотацию компилятора, чтобы вызвать выполнение функции при загрузке базового двоичного файла/dylib. Тем не менее, в это время вы можете сделать очень мало.

__attribute__((constructor)) 
static void MySuperEarlyInitialization() {...} 

Вы намного лучше выполняете свою инициализацию в ответ на приносимое приложение. NSApplication и UIApplication обе предлагают делегатские/уведомляющие крючки для инъекции немного кода в приложение при его запуске.

+0

Спасибо! Я подумал, что должно быть что-то вроде этого ... мой единственный вопрос: будет ли это работать для статической библиотеки? –

+2

Да, все будет хорошо. Статическая библиотека - это не что иное, как набор файлов .o, которые связаны с приложением, как будто они были скомпилированы в первую очередь. Обратите внимание, что, тем не менее, не выполнение инициализации в таких конструкторах - лучший долгосрочный план .... – bbum

0

переменный типа NSString *const всегда будет инициализированы перед запуском вашего кода, предполагая, что мы игнорировать C капризы ++ на данный момент:

NSString *const MY_PROTOCOL_SIZE = @"..."; 

переменного типа const NSString *const ключевом слове, применяя к кишкам NSString , а не его адрес) могут быть изменены любым кодом, но не могут отправлять сообщения на него. Это побеждает цель сделать это const. Рассмотрим вместо глобальной функции:

static NSString *GetMyProtocolSize(void) { 
    return [[MyClass someStringLoadedFromAFile] ...]; 
} 

Или использовать метод класса:

@implementation MyClass 
+ (NSString *)myProtocolSize { 
    return [[MyClass someStringLoadedFromAFile] ...]; 
} 
@end 

Вы задали вопрос о том, почему раньше ваши const строки не будет принимать динамические значения - это происходит потому, что вы не делаете похоже, понимают, что делает const. Вы должны прочитать значение ключевого слова const в C и посмотреть на другой подход к получению ваших строк, если const не является правильным.

2

Почему бы вам не настроить эти две переменные внутри класса MyClass? А также, почему вы не используете аксессоров? Вместо того, чтобы иметь поддельную постоянную переменную, которая исходит из ниоткуда, предпочтительнее определить аксессуар для класса, который должен его использовать. Простой + (NSString *) myProtocolSize; будет делать все, даже в протоколе.

Кроме того, переопределение методов класса в категории «работает», но не является надежным и его следует избегать любой ценой: если метод, который вы переопределяете, реализуется в категории, среда выполнения НЕ гарантирует загрузку порядок и ваша реализация никогда не будут добавлены к нему.

+0

На самом деле, существует более 20 констант, и создание класса действительно неотесанно. –

 Смежные вопросы

  • Нет связанных вопросов^_^