Статические инициализаторы в объекте C
Как сделать статические инициализаторы в objective-c (если у меня есть правильный термин). В основном я хочу сделать что-то вроде этого:
static NSString* gTexts[] =
{
@"A string.",
@"Another string.",
}
Но я хочу сделать это более структурированным, т.е. иметь не только NSString для каждого элемента в этом массиве, но вместо NSString плюс один NSArray, который содержит переменное число MyObjectType, где MyObjectType будет содержать NSString, пару ints и т.д.
Ответы
Ответ 1
Так как NSArrays
и MyObjectTypes
являются объектами, выделенными кучами, их невозможно создать в статическом контексте. Вы можете объявить переменные, а затем инициализировать их в методе.
Так что вы не можете сделать:
static NSArray *myStaticArray = [[NSArray alloc] init....];
Вместо этого вы должны сделать:
static NSArray *myStaticArray = nil;
- (void) someMethod {
if (myStaticArray == nil) {
myStaticArray = [[NSArray alloc] init...];
}
}
Это происходит с постоянными строками (@"foo"
и т.д.), потому что они не распределены по кучам. Они жестко закодированы в двоичный файл.
Ответ 2
Очень важно, чтобы ваша статическая инициализация была потокобезопасной (доступна в iOS 4.1 +)!!!
static NSArray *myStaticArray = nil;
- (void) someMethod {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
myStaticArray = [[NSArray alloc] init...]
});
}
Ответ 3
здесь один из способов, если вы можете жить с преобразованием objС++:
#import <Foundation/Foundation.h>
namespace { // ok, this storage should preferably be in a function/deferred
static struct sa { NSString* const s; NSArray* const a; } r = {
[[NSString alloc] initWithString:@"hello"],
[[NSArray alloc] initWithObjects:@"w", @"o", @"r", @"l", @"d", @"= =", nil]
};
}
int main(int argc, const char* argv[]) {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSLog(@"\n\n%@...\n\n...\n%@", r.s, r.a);
[pool drain];
return 0;
}
Ответ 4
Метод + initialize вызывается автоматически при первом использовании класса, прежде чем будут применены какие-либо методы класса или созданы экземпляры.
+ (void) initialize {
if (self == [MyClass class]) {
// Once-only initializion
}
// Initialization for this class and any subclasses
}
+ initialize наследуется подклассами, а также вызывается для каждого подкласса, который не реализует собственную инициализацию+. Это может быть особенно проблематично, если вы наивно реализуете инициализацию singleton в + initialize. Решение состоит в проверке типа переменной класса.
p.s Вы никогда не должны вызывать + инициализировать себя.