Objective-C статические, внешние, открытые переменные

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

static BOOL LogStuff = NO;

и в методе initialize я устанавливаю значение ведения журнала:

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

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

static extern BOOL LogStuff;

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

5 ответов


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

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

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

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

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


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

+ (void)setLogStuff:(BOOL)aLogStuff;
+ (BOOL)logStuff;

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


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

// .h
static NSString * aStatic;

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

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

// .h
extern NSString * anExtern;

// .m
NSString * anExtern = @"global";

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

NSMutableArray *macroArray;
BOOL keepMacro;

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

    [macroArray removeAllObjects];
    keepMacro = YES;
}

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

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