Статические переменные класса Objective C

Я новичок в Objective C и читаю книгу под названием "Visual Quickstart Guide: Objective-C" Стивена Хольцнера, Press Peachpit Press

В главе 6: Объектно-ориентированное программирование имеется раздел "Использование переменных класса", где он пишет:

Вы можете создавать переменные класса для использования с ваши классы, но theres заминка: каждый объект этого класса имеет одну и ту же переменную, поэтому если один объект изменяет переменную класса, то переменная изменяется для всех объектов. Вы создаете переменные класса со статическим ключевым словом. Переменные класса часто полезны: например, вы можете использовать переменную класса, чтобы отслеживать количество созданных объектов определенного класса в программе. Вы сделаете это в этой задаче.

И говорит ввести следующий код:

#import <stdio.h>
#import <Foundation/NSObject.h>
@interface TheClass: NSObject
static int count; //error: cannot declare variable inside @interface or @protocol
+(int) getCount;
@end
...

Этот код дает мне ошибку в Xcode 4:

Невозможно объявить переменную внутри @interface или @protocol

Является ли книга неправильной или я делаю что-то неправильно?

Ответ 1

Вы объявляете статическую переменную в файле реализации (.m файл). Это должно работать:

// TheClass.h
@interface TheClass : NSObject
+ (int)count;
@end

// TheClass.m
static int theCount = 0;

@implementation TheClass
+ (int) count { return theCount; }
@end

Это не переменная класса per se; Objective-C не имеет понятия переменной класса. Однако в сочетании с методом класса для извлечения этой переменной он работает аналогично переменной класса. Тем не менее, это действительно просто статическая переменная C, доступная для реализации класса.

Ответ 2

Я видел один Visual Quickstart Guide о Unix, и он сосал большое время. Кажется, что это не намного лучше, по крайней мере, из образца. Правильный способ создания переменной класса в Objective-C выглядит следующим образом:

// Counted.h
@interface Counted : NSObject

+ (NSUInteger) numberOfInstances;

@end

// Counted.m
#import "Counted.h"

static NSUInteger instances = 0;

@implementation Counted

- (id) init {
    …
    instances++;
    …
}

- (void) dealloc {
    instances--;
}

+ (NSUInteger) numberOfInstances {
    return instances;
}

@end

Это фактически статическая переменная, а не настоящая переменная класса. Но вы не должны слишком беспокоиться о переменных класса, они обычно являются признаком того, что вы делаете что-то неправильно. (Я немного упрощаю, но не много.)

Если вы ищете достойную книгу Objective-C, прочитайте одну из них Apple. Его свободное и хорошее чтение.

Ответ 3

Если для переменной класса требуется более тривиальная инициализация, используйте dispatch_once:

@interface Foo ()
+ (Foo *)singleton;
@end

+ (Foo *)singleton {
    static Foo *_singleton;
    static dispatch_once_t oncePredicate;

    dispatch_once(&oncePredicate, ^{
        _singleton = [[Foo alloc] init];
    });

    return _singleton;
}

Ответ 4

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

#import "TheClass.h"

static int count;

@implementation

...

@end

Важно отметить, что Objective-C фактически не поддерживает переменные класса. Но вы можете имитировать их со статическими переменными, как мы это делаем.