8

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

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

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

idGen 方法:

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

3 回答 3

42

2017 年更新

Xcode 8 向 Objective-C 引入了类属性,来自发行说明:

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

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

@interface PlayerMenuController : NSObject

@property (class) int idGen;

@end

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


原始答案

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

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

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

示例界面:

@interface PlayerMenuController : NSObject

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

@end

实施:

@implementation PlayerMenuController

static int idGen = 0;

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

@end

并测试它:

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

生产:

initial value: 0
updated value: 42

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

于 2013-04-12T20:30:08.317 回答
3

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

安全的方法是使用 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);
}
于 2014-07-08T10:30:53.300 回答
1

您不应该返回self.idGen,因为 anint不是属性。如果您这样做,您的代码应该可以工作:

 + (int) idGen {
     static int idGen;
     return idGen;
   }
于 2013-04-12T20:11:46.893 回答