Objective-C статические, внешние, публичные переменные - PullRequest
38 голосов
/ 04 октября 2011

Я хочу иметь переменную, к которой я могу получить доступ где угодно, импортируя файл заголовка, но я также хочу, чтобы она была статической в ​​том смысле, что создается только одна из них.В моем файле .m я указываю

static BOOL LogStuff = NO;

, а в методе инициализации я устанавливаю значение регистрации:

+ (void)initialize
{
    LogStuff = ... //whatever
}

Однако я хочу иметь доступ к моей переменной в любом месте, импортируяфайл .h, поэтому я хочу сделать что-то вроде этого:

static extern BOOL LogStuff;

, но мне не разрешено это делать.Можно ли сделать то, что я пытаюсь сделать?Спасибо

Ответы [ 5 ]

123 голосов
/ 04 октября 2011

static в Objective-C означает нечто иное, чем static в классе C ++, в контексте членов данных статического класса и методов статического класса.В C и Objective-C переменная или функция static в глобальной области означает, что этот символ имеет внутреннюю связь .

Внутренняя связь означает, что этот символ является локальным по отношению к текущему единица перевода , которая является текущим исходным файлом (.c или .m), который компилируется и все файлы заголовков, которые он рекурсивно включает.На этот символ нельзя ссылаться из другой единицы перевода, и у тебя могут быть другие символы с внутренней связью в других единицах перевода с тем же именем.

Так, если у тебя есть файл заголовка, объявляющий переменную как staticкаждый исходный файл, который включает этот заголовок, получает отдельную глобальную переменную - все ссылки на эту переменную в одном исходном файле будут ссылаться на одну и ту же переменную, но ссылки в разных исходных файлах будут ссылаться на разные переменных.

Если вы хотите иметь одну глобальную переменную, вы не можете иметь ее в области видимости класса, как в C ++.Один из вариантов - создать глобальную переменную с внешней связью : объявить переменную с ключевым словом extern в заголовочном файле, а затем в одном исходном файле определить ее в глобальной области видимостибез ключевого слова extern.Внутренняя связь и внешняя связь являются взаимоисключающими - вы не можете иметь переменную, объявленную как extern и static.

Альтернативой, как Panos предложил , было бы использование классаметод вместо переменной.Это сохраняет функциональность в рамках класса, что имеет смысл семантически, и вы также можете сделать это @private, если хотите.Это добавляет незначительное снижение производительности, но это вряд ли будет узким местом в вашем приложении (если вы подозреваете, что это так, всегда сначала профилируйте).

4 голосов
/ 04 октября 2011

Если LogStuff является полем статического класса, может быть, вы можете реализовать статический метод получения и установки?

3 голосов
/ 04 октября 2011

Объявите это extern BOOL в вашем заголовочном файле. Файлы, которые #import вашего заголовка не знают или не заботятся, является ли внешний символ статическим или нет.

1 голос
/ 28 июля 2015

Отдельная глобальная переменная (одна на исходный файл):

// .h
static NSString * aStatic;

//.m
static NSString * aStatic = @"separate";

Уникальная глобальная переменная:

// .h
extern NSString * anExtern;

// .m
NSString * anExtern = @"global";
0 голосов
/ 04 октября 2011

Я обычно использую этот макет для моей статики:

NSMutableArray *macroArray;
BOOL keepMacro;

+ (void) startMacro
{
    if (macroArray == nil)
    {
        macroArray = [[NSMutableArray alloc] initWithCapacity:100];
    }

    [macroArray removeAllObjects];
    keepMacro = YES;
}

Это команда startMacro в моем приложении. И Bool, и macroArray являются статическими, но обратите внимание, что они не объявлены static или extern.

Возможно, это не лучшая практика, но это то, что я делаю.

...