Статическая строковая переменная в Objective C на iphone

Как создать и получить доступ к статической строке в iPhone (цель c)? Объявляю static NSString *str = @"OldValue" в классе А.

Если я присвою ему какое-то значение в классе B как str = @"NewValue". Это значение сохраняется для всех методов в классе B. Но если я обращаюсь к нему в классе C (после присвоения в B), я получаю его как OldValue. Я что-то упускаю? Должен ли я использовать extern в других классах?

С уважением и уважением, Йогини


person Yogini    schedule 11.06.2009    source источник


Ответы (2)


Обновление. Начиная с Xcode 8, Objective-C имеет свойства класса. Обратите внимание, это в основном синтаксический сахар; эти свойства не синтезируются автоматически, поэтому реализация в основном не изменилась по сравнению с предыдущими.

// MyClass.h
@interface MyClass : NSObject
@property( class, copy ) NSString* str;
@end

// MyClass.m
#import "MyClass.h"

@implementation MyClass

static NSString* str;

+ (NSString*) str 
{
    return str;
}

+ (void) setStr:(NSString*)newStr 
{
    if( str != newStr ) {
        str = [newStr copy];
    }
}
@end


// Client code
MyClass.str = @"Some String";
NSLog( @"%@", MyClass.str ); // "Some String"

См. WWDC 2016 Что нового в LLVM. Часть свойства класса начинается примерно на отметке 5 минут.

Исходный ответ:

Objective-C не имеет переменных класса, что, я думаю, вы ищете. Вы можете как бы подделать это с помощью статических переменных, как вы это делаете.

Я бы рекомендовал поместить статический NSString в файл реализации вашего класса и предоставить методы класса для доступа / изменения его. Что-то вроде этого:

// MyClass.h
@interface MyClass : NSObject {
}
+ (NSString*)str;
+ (void)setStr:(NSString*)newStr;
@end

// MyClass.m
#import "MyClass.h"

static NSString* str;

@implementation MyClass

+ (NSString*)str {
    return str;
}

+ (void)setStr:(NSString*)newStr {
    if (str != newStr) {
        [str release];
        str = [newStr copy];
    }
}
@end
person zpasternack    schedule 11.06.2009

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

Одна вещь, о которой вы не упомянули, - это связь между классами A, B и C. Если они находятся в иерархии наследования и вы ожидаете, что статическая переменная будет унаследована, как в Java, метод, описанный zpasternack будет работать.

Если три класса не связаны между собой, и вы просто хотите получить доступ к значению, объявленному в A, то extern - более подходящий способ. В этом случае вы хотите объявить переменную как extern в ClassA.h, а затем определить ее в Class.m. Пока ClassB и ClassC импортируют ClassA.h, они смогут связываться с одним и тем же определением extern.

Один замечательный момент заключается в том, что вместо использования extern самого по себе более надежно использовать OBJC_EXPORT, который определен в objc-api.h и также обрабатывает компиляцию под C ++. Вот пример кода:

// ClassA.h
OBJC_EXPORT NSString* commonString;
...

// ClassA.m
NSString* commonString = @"OldValue";

// ClassB.m
#import "ClassA.h"
...
commonString = @"NewValue"; // Can be inside a function or method

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

person Quinn Taylor    schedule 11.06.2009
comment
Это OBJC_EXPORT или OBJC_EXTERN мы должны использовать? - person Bryce Thomas; 08.06.2013