Определение константы в цели-c

Я часто использую : tabo , чтобы закрыть все остальные вкладки.

16
задан Quinn Taylor 30 June 2009 в 02:37
поделиться

2 ответа

Прелюдия: Полезно понимать разницу между директивами прекомпилятора и истинными константами. #define просто выполняет замену текста до того, как компилятор построит код. Это отлично подходит для числовых констант и определений типов, но не всегда является лучшей идеей для вызовов функций или методов. Я исхожу из предположения, что вам действительно нужна настоящая константа, а это означает, что код для создания пути поиска должен выполняться только один раз.


В вашем файле MyClass.m определите переменную и заполните его методом + initialize следующим образом:

static NSArray *documentsDir;

@implementation MyClass

+ (void) initialize {
    if (documentsDir == nil) {
        documentsDir = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES) lastObject] retain];
    }
}

...

@end

Модификатор static делает его видимым только в той единице компиляции, где он объявлен. Для простой константы это все, что вам нужно.

Если у класса есть подклассы, + initialize будет вызываться один раз для каждого подкласса (по умолчанию), поэтому вам нужно проверить, равен ли documentsDir nil , прежде чем назначать ему, чтобы вы не допускайте утечки памяти. (Или, как указывает Питер Льюис, вы можете проверить, является ли инициализируемый в настоящее время класс MyClass, используя метод == или -isMemberOfClass: .) Если подклассы также необходим прямой доступ к константе, вам нужно будет предварительно объявить переменную как extern в файле MyClass.h (который включают дочерние классы):

extern NSArray *documentsDir;

@interface MyClass : NSObject
...
@end

Если вы предварительно -объявление переменной как extern, вы должны удалить ключевое слово static из определения, чтобы избежать ошибок компиляции. Это необходимо, чтобы переменная могла охватывать несколько единиц компиляции. (Ах, радости C ...)

Примечание: В коде Objective-C лучший способ объявить что-то как extern - использовать OBJC_EXPORT (a #define объявлен в ), который устанавливается в зависимости от того, используете ли вы C ++. Просто замените extern на OBJC_EXPORT , и все готово.


Изменить: Я только что наткнулся на вопрос SO .

34
ответ дан 30 November 2019 в 15:52
поделиться

Самое простое решение - просто изменить пути, чтобы они были статической переменной, и вычислить ее только один раз, например:

+(NSString *) getDocumentsDir {
    static NSString *documentsDir = nil;
    if ( !documentsDir ) {
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
        documentsDir = [paths objectAtIndex: 0];
    }
    return documentsDir;
}

«static» сообщает компилятору, что documentsDir фактически является глобальной переменной, хотя доступен только внутри функции. Таким образом, он инициализируется значением nil, и первый вызов getDocumentsDir оценивает его, а затем последующие вызовы возвращают предварительно оцененное значение.

12
ответ дан 30 November 2019 в 15:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: