2013-12-02 5 views
2

В Objective-C существует ли способ запуска определенного селектора автоматически при каждом экземпляре объекта? (Я знаю о +initialize, но мне нужен метод экземпляра).Автоматический запуск селектора при создании экземпляра

В частности, я пишу пользовательский класс строк (который наследуется от моего собственного корневого класса с аналогичным интерфейсом до NSObject), и я пытаюсь заставить его «отлично играть» с константными строками Objective-C. Для этого у меня есть следующее определение класса (в соответствии с требованиями выполнения):

// 1) Required Layout 
@interface MYConstantString : MYObject { 
    //Class isa; inherited from MYObject 
    char *c_string; 
    unsigned int length; 
} 

Теперь я хочу, чтобы реализовать свой струнный класс, используя указатель на C-структуры внутри класса (это «C объект "уже хорошо реализован, поэтому я просто хочу обернуть его в класс Objective-C). В идеале, следовательно, мой класс Objective-C будет выглядеть следующим образом:

// 2) Desired Laout 
@interface MYConstantString : MYObject { 
    // Class isa; 
    StringObject *string; 
} 

И тогда методы класса и экземпляра просто оберните функция C вызовы с помощью этого StringObject.

Так как я не могу иметь желаемую компоновку ивара (2), я хотел бы взломать требуемый макет ivar (1), чтобы работать на меня. Например:

- (void)fixup { 
    // Pseudocode 
    temp = copystring(c_string); 
    c_string = (void *)StringObjectNewWithString(temp); // Fudge pointer 
    length = ... // I can do something else with this. 
} 

Таким образом, чтобы вернуться к вопросу, есть ли способ вызова -fixup автоматически, вместо того, чтобы сделать следующий каждый раз, когда я делаю написать постоянную строку Objective-C?

MYConstantString *str = @"Constant string"; 
[str fixup]; 

Я знаю, что это непристойно хак, и Objective-C постоянная строка совместимости не является абсолютно решающим для того, что мне нужно, но было бы неплохо, чтобы иметь возможность использовать синтаксис @"" и сделать код более «естественно» Цель-C.

ответ

1

Я предполагаю, что вы оставили важный факт: вы используете -fconstant-string-class=MYConstantString при создании, чтобы компилятор использовал ваш класс для постоянных строковых объектов (@"...").

Учитывая это, тогда нет. Есть две существенные проблемы. Во-первых, «создание экземпляра» для постоянных строк происходит во время компиляции, а не во время выполнения. Причина, по которой требуется макет, заключается в том, что компилятор ничего не делает, кроме как выкладывает данные строки в разделе данных со ссылкой на соответствующий объект класса, куда идет указатель isa. Он не вызывает какой-либо пользовательский код. При компиляции не обязательно даже знать такой код. Данная единица перевода может не содержать константный класс строк. Ссылка на это разрешена во время соединения.

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

Вам следует рассмотреть возможность использования кластера классов. Сделайте MYConstantString одним конкретным подклассом абстрактного базового класса. Сделайте его соответствующим требуемому макету и просто используйте указатель на символ и длину ivars, как они есть. Если было бы удобно перевести на StringObject в разные моменты, сделайте это в этих точках. Внедрите другие, отдельные бетонные подклассы, чтобы при необходимости использовать StringObject.

+0

Простите, да, 'MYConstantString', а не' NSConstantString'. Я рассмотрел кластер классов, но я не думал о переводе и выходе из StringObject - возможно, лучший способ получить то, что мне нужно, спасибо! – Ephemera

0
MYConstantString *str = @"Constant string"; 

Это не может работать, потому что @"..." является NSString, и это не только проблема компоновки, но размеров экземпляров. Если вы хотите 0-копию или что-нибудь подобное, что вы должны сделать, это что-то вроде:

MYConstantString *str = [MyConstantString stringWithNSString:@"Constant string"]; 

и пусть -stringWithNSString: распознать, когда переданная строка является константой один (я уверен, что конкретный класс постоянные строки легко распознаются и, вероятно, никогда не изменялись по причинам обратной совместимости), а затем взломать его, чтобы захватить указатель на байты и подобные вещи.

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