2009-06-30 2 views
139

У меня есть класс Film, каждый из которых хранит уникальный идентификатор. В C#, Java и т. Д. Я могу определить статический int currentID, и каждый раз, когда я устанавливаю ID, я могу увеличить currentID, и изменение происходит на уровне класса, а не на уровне объекта. Можно ли это сделать в Objective C? Мне было очень трудно найти ответ для этого.Objective C Статические переменные уровня класса

ответ

28

О файле .m, вы можете объявить переменную как статические:

static ClassName *variableName = nil; 

Затем вы можете инициализировать его на методе +(void)initialize.

Обратите внимание, что это простая статическая переменная C и не является статичной в смысле Java или C#, но она даст аналогичные результаты.

+3

исправьте: '+ (void) initialize' является методом – monkeydom

11

Как сказано в pgb, нет «переменных класса», только «переменных экземпляра». Объективный способ выполнения переменных класса - это статическая глобальная переменная внутри .m-файла класса. «Статический» гарантирует, что переменная не может использоваться вне этого файла (т. Е. Она не может быть extern).

16

В файле .m, объявить глобальную переменную файла:

static int currentID = 1; 

то в вашей обычной инициализации, Refernce что:

- (id) init 
{ 
    self = [super init]; 
    if (self != nil) { 
     _myID = currentID++; // not thread safe 
    } 
    return self; 
} 

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

155

Выпуск Описание:

  1. Вы хотите, чтобы ваш ClassA иметь переменный класс ClassB.
  2. Вы используете Objective-C в качестве языка программирования.
  3. Objective-C не поддерживает переменные класса, как это делает C++.

Одна альтернатива:

Имитировать переменную поведение класса, используя Objective-C оснащен

  1. Declare/Определить статическую переменную внутри classA.m так он будет доступен только для методы класса A (и все, что вы помещаете внутри классаA.m).

  2. Перезаписать метод инициализации класса NSObject для инициализации только после статической переменной с экземпляром ClassB.

  3. Вам будет интересно, почему я должен перезаписать метод инициализации NSObject. Документация Apple об этом методе имеет ответ: «Время выполнения отправляет инициализацию каждому классу в программе ровно один раз перед классом или любым наследуемым от него классом, отправляется его первое сообщение из программы (таким образом, метод никогда не будет вызываться, если класс не используется.) ».

  4. Не стесняйтесь использовать статическую переменную в любом классе ClassA class/instance.

Пример кода:

файл: classA.m

static ClassB *classVariableName = nil; 

@implementation ClassA 

... 

+(void) initialize 
{ 
    if (! classVariableName) 
     classVariableName = [[ClassB alloc] init]; 
} 

+(void) classMethodName 
{ 
    [classVariableName doSomething]; 
} 

-(void) instanceMethodName 
{ 
    [classVariableName doSomething]; 
} 

... 

@end 

Ссылки:

  1. Class variables explained comparing Objective-C and C++ approaches
+3

У вас есть статическая переменная типа ClassA в классеA.m? – goatlinks

+0

@goatlinks - Да. – DougW

+6

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

26

Начиная с Xcode 8 вы можете определить свойства класса в Obj-C. Это добавлено для взаимодействия со статическими свойствами Swift.

Objective-C теперь поддерживает свойства класса, которые взаимодействуют со свойствами типа Swift. Они объявляются как: @property (класс) NSString * someStringProperty ;. Они никогда не синтезируются. (23891898)

Вот пример

@interface YourClass : NSObject 

@property (class, nonatomic, assign) NSInteger currentId; 

@end 

@implementation YourClass 

static NSInteger _currentId = 0; 

+ (NSInteger)currentId { 
    return _currentId; 
} 

+ (void)setCurrentId:(NSInteger)newValue { 
    _currentId = newValue; 
} 

@end 

Тогда вы можете получить доступ к нему, как это:

YourClass.currentId = 1; 
val = YourClass.currentId; 

Вот очень интересный explanatory post я использовал в качестве ссылки для редактирования этого старого ответ.


2011 Ответ: (не используйте это, это ужасно)

Если вы действительно не хотите, чтобы объявить глобальную переменную, есть еще один вариант, может быть, не очень ортодоксальный: -), но работает ... вы можете объявить метод «получить & набор», как это, с статической переменной внутри:

+ (NSString*)testHolder:(NSString*)_test { 
    static NSString *test; 

    if(_test != nil) { 
     if(test != nil) 
      [test release]; 
     test = [_test retain]; 
    } 

    // if(test == nil) 
    //  test = @"Initialize the var here if you need to"; 

    return test; 
} 

Так что, если вам нужно получить значение, просто позвоните:

NSString *testVal = [MyClass testHolder:nil] 

И тогда, когда вы хотите, чтобы установить его:

[MyClass testHolder:testVal] 

В случае, если вы хотите, чтобы иметь возможность установить этот псевдо-статическую-вар к нулю, вы можете объявить testHolder как это:

+ (NSString*)testHolderSet:(BOOL)shouldSet newValue:(NSString*)_test { 
    static NSString *test; 

    if(shouldSet) { 
     if(test != nil) 
      [test release]; 
     test = [_test retain]; 
    } 

    return test; 
} 

И два удобный способ:

+ (NSString*)test { 
    return [MyClass testHolderSet:NO newValue:nil]; 
} 

+ (void)setTest:(NSString*)_test { 
    [MyClass testHolderSet:YES newValue:_test]; 
} 

Надеется, что это помогает! Удачи.

+0

Прохладный, но это не глобальная переменная, потому что к нему нельзя получить доступ из других файлов '.m', и я думаю, что это нормально для того, чтобы он был« глобальным »в файле' Class.m'. – ma11hew28

3

Вот бы вариант:

+(int)getId{ 
    static int id; 
    //Do anything you need to update the ID here 
    return id; 
} 

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

0

u может переименовать класс как classA.мм и добавить в него возможности C++.

2

(Строго говоря, не ответ на вопрос, но в моем опыте, вероятно, будет полезно при поиске переменного класса)

Метод класса часто может играть много ролей переменного класса будет на других языках (например, изменили конфигурацию во время тестирования):

@interface MyCls: NSObject 
+ (NSString*)theNameThing; 
- (void)doTheThing; 
@end 
@implementation 
+ (NSString*)theNameThing { return @"Something general"; } 
- (void)doTheThing { 
    [SomeResource changeSomething:[self.class theNameThing]]; 
} 
@end 

@interface MySpecialCase: MyCls 
@end 
@implementation 
+ (NSString*)theNameThing { return @"Something specific"; } 
@end 

Теперь объект класса MyCls вызовов Resource:changeSomething: со строкой @"Something general" на призыв к doTheThing:, но объект, полученный из MySpecialCase со строкой @"Something specific" ,

0

Еще одна возможность - иметь небольшой NSNumber подкласс singleton.

Смежные вопросы