Подтвердить что ты не робот

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

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

static BOOL LogStuff = NO;

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

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

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

static extern BOOL LogStuff;

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

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

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

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

Ответ 3

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

Ответ 4

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

NSMutableArray *macroArray;
BOOL keepMacro;

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

    [macroArray removeAllObjects];
    keepMacro = YES;
}

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

Это не лучшая практика, но это то, что я делаю.

Ответ 5

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

// .h
static NSString * aStatic;

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

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

// .h
extern NSString * anExtern;

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