ios 在 Objective C 中设置静态变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15979973/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 23:09:58  来源:igfitidea点击:

Setting static variables in Objective C

iphoneiosobjective-cvariablesstatic

提问by Declan McKenna

I can't seem to find a way to set the static int I have created to assign unique ids to every object I save to persistent memory. The following gives me a 'no setter method 'setIdGen' for assignment to property.

我似乎找不到一种方法来设置我创建的静态 int 来为我保存到持久内存的每个对象分配唯一的 id。以下为我提供了一个用于分配给属性的“无设置方法”“setIdGen”。

-(void)viewDidLoad
{
    PlayerMenuController.idGen = [[NSUserDefaults standardUserDefaults] floatForKey:@"idGen"];
}

As well as the above I've tried creating a static setIdGen method that would return bad access errors, and making NSIntegers with their own set methods. My static NSMutableArray gave the same errors when I tried to assign it using = but worked fine when using setArray.

除了上述内容,我还尝试创建一个静态 setIdGen 方法,该方法会返回错误访问错误,并使用自己的 set 方法制作 NSIntegers。当我尝试使用 = 分配它时,我的静态 NSMutableArray 给出了相同的错误,但在使用 setArray 时工作正常。

idGen method:

idGen 方法:

+ (int) idGen
{
    /*static int idGen;
    if(!idGen)
    {
        idGen = 0;
        NSLog(@"idGen reset");
    }*/
    return self.idGen;
}

回答by CRD

Update 2017

2017 年更新

Xcode 8 introduced class properties to Objective-C, from the release notes:

Xcode 8 从发行说明中向 Objective-C 引入了类属性:

Objective-C now supports class properties, which interoperate with Swift type properties. They are declared as @property (class) NSString *someStringProperty;, and are never synthesised.

Objective-C 现在支持与 Swift 类型属性互操作的类属性。它们被声明为@property (class) NSString *someStringProperty;,并且永远不会被合成。

This means our sample interface below can become:

这意味着我们下面的示例界面可以变成:

@interface PlayerMenuController : NSObject

@property (class) int idGen;

@end

Howeveryou must still implement the methods yourself, as shown below, as class properties are never synthesised. Note that this also means if you specify property attributes, such as copy, that your methods must implement the semantics.

但是,您仍然必须自己实现这些方法,如下所示,因为类属性永远不会被合成。请注意,这也意味着如果您指定属性属性,例如copy,您的方法必须实现语义。



Original Answer

原答案

It looks like you are trying to implement a class property, but there is not such thing in Objective-C - a property is a pair of instance methods.

看起来您正在尝试实现类属性,但在 Objective-C 中没有这样的东西 - 属性是一对实例方法。

However, you can fake it...

但是,你可以伪造它......

While the @propertydeclaration is not available to you, if you declare class methods which follow the right naming convention then your compiler may(tested on Xcode 4.6.1, "may" as I cannot offhand point to this being supported, but it's simple to test and will compile time error if not) allow you to use dot notation, i.e. it looks like a class property even if it lacks an @property.

虽然@property声明对您不可用,但如果您声明遵循正确命名约定的类方法,那么您的编译器可能(在 Xcode 4.6.1 上测试,“可能”,因为我无法直接指出支持这一点,但测试很简单并且如果不是,则会编译时错误)允许您使用点表示法,即它看起来像一个类属性,即使它缺少@property.

A sample interface:

示例界面:

@interface PlayerMenuController : NSObject

// a class "property"
+ (int) idGen;
+ (void) setIdGen:(int)value;

@end

The implementation:

实施:

@implementation PlayerMenuController

static int idGen = 0;

+ (int) idGen { return idGen; }
+ (void) setIdGen:(int)value { idGen = value; }

@end

And test it:

并测试它:

NSLog(@"initial value: %d", PlayerMenuController.idGen);
PlayerMenuController.idGen = 42;
NSLog(@"updated value: %d", PlayerMenuController.idGen);

producing:

生产:

initial value: 0
updated value: 42

So we have a "class property" - it looks, walks and quacks like a property ;-)

所以我们有一个“类财产”——它看起来、走路和嘎嘎声都像一个财产;-)

回答by GreatWiz

If you use a static variable and you ever want to subclass this, the static variable will be the same for both parent and child, so any change when addressing the child class, will also change the same 'property' on it's parent. (and vice versa)

如果您使用静态变量并且您想对其进行子类化,则父类和子类的静态变量将相同,因此在对子类进行寻址时,任何更改都会更改其父类上的相同“属性”。(反之亦然)

The safe way to do it is using objc/runtime.h associated objects

安全的方法是使用 objc/runtime.h 关联对象

+(int) idGen
{
    NSNumber* idGen = objc_getAssociatedObject(self, @selector(idGen));

    if (idGen == nil)
    {
        idGen = @0;
    }
    else
    {
        idGen = @([idGen intValue] + 1);
    }

    self.idGen = [idGen intValue];

    return [idGen intValue];
}

+(void)setIdGen:(int)idGen
{
    objc_setAssociatedObject(self, @selector(idGen), @(idGen), OBJC_ASSOCIATION_RETAIN);
}

回答by Mike Z

You shouldn't be returning self.idGenbecause an intis not a property. Your code should work if you do this:

你不应该回来,self.idGen因为 anint不是财产。如果您这样做,您的代码应该可以工作:

 + (int) idGen {
     static int idGen;
     return idGen;
   }