如何在Objective-C中声明类级属性?

时间:2009-03-30 04:09:05

标签: objective-c cocoa oop

也许这很明显,但我不知道如何在Objective-C中声明类属性。

我需要为每个类缓存一个字典,并想知道如何把它放在课堂上。

10 个答案:

答案 0 :(得分:184)

属性在Objective-C中具有特定含义,但我认为你的意思是等同于静态变量?例如。所有类型的Foo只有一个实例?

要在Objective-C中声明类函数,请使用+前缀而不是 - 所以您的实现看起来像:

// Foo.h
@interface Foo {
}

+ (NSDictionary *)dictionary;

// Foo.m
+ (NSDictionary *)dictionary {
  static NSDictionary *fooDict = nil;
  if (fooDict == nil) {
    // create dict
  }
  return fooDict;
}

答案 1 :(得分:106)

我正在使用这个解决方案:

@interface Model
+ (int) value;
+ (void) setValue:(int)val;
@end

@implementation Model
static int value;
+ (int) value
{ @synchronized(self) { return value; } }
+ (void) setValue:(int)val
{ @synchronized(self) { value = val; } }
@end

我发现它作为Singleton模式的替代品非常有用。

要使用它,只需使用点符号访问您的数据:

Model.value = 1;
NSLog(@"%d = value", Model.value);

答案 2 :(得分:68)

如WWDC 2016 / XCode 8(what's new in LLVM session @ 5:05)所示。类属性可以声明如下

@interface MyType : NSObject
@property (class) NSString *someString;
@end

NSLog(@"format string %@", MyType.someString);

请注意,类属性永远不会被合成

@implementation
static NSString * _someString;
+ (NSString *)someString { return _someString; }
+ (void)setSomeString:(NSString *)newString { _someString = newString; }
@end

答案 3 :(得分:63)

如果你正在寻找等级为@property的班级等级,那么答案就是“没有这样的东西”。但请记住,@property只是语法糖,无论如何;它只是创建了适当命名的对象方法。

您希望创建访问静态变量的类方法,正如其他人所说,这些方法的语法略有不同。

答案 4 :(得分:21)

这是一种线程安全的方法:

// Foo.h
@interface Foo {
}

+(NSDictionary*) dictionary;

// Foo.m
+(NSDictionary*) dictionary
{
  static NSDictionary* fooDict = nil;

  static dispatch_once_t oncePredicate;

  dispatch_once(&oncePredicate, ^{
        // create dict
    });

  return fooDict;
}

这些编辑确保只创建一次fooDict。

From Apple documentation:“dispatch_once - 在应用程序的生命周期内执行一次且仅执行一次块对象。”

答案 5 :(得分:11)

从Xcode 8开始,Objective-C现在支持类属性:

@interface MyClass : NSObject
@property (class, nonatomic, assign, readonly) NSUUID* identifier;
@end

由于类属性永远不会被合成,因此您需要编写自己的实现。

@implementation MyClass
static NSUUID*_identifier = nil;

+ (NSUUID *)identifier {
  if (_identifier == nil) {
    _identifier = [[NSUUID alloc] init];
  }
  return _identifier;
}
@end

您可以使用类名称上的常规点语法访问类属性:

MyClass.identifier;

答案 6 :(得分:7)

属性仅在对象中具有值,而不是类。

如果需要为类的所有对象存储内容,则必须使用全局变量。您可以通过在实现文件中声明static来隐藏它。

您还可以考虑使用对象之间的特定关系:将master的角色归因于类的特定对象,并将其他对象链接到此master。主人将字典作为一个简单的属性。我想到的树就像Cocoa应用程序中用于视图层次结构的树。

另一种选择是创建一个专用类的对象,该对象由“类”字典和与该字典相关的所有对象组成。这与Cocoa中的NSAutoreleasePool类似。

答案 7 :(得分:5)

从Xcode 8开始,您可以使用Berbie回答的 class 属性属性。

但是,在实现中,您需要使用静态变量代替iVar为class属性定义类getter和setter。

Sample.h

@interface Sample: NSObject
@property (class, retain) Sample *sharedSample;
@end

Sample.m

@implementation Sample
static Sample *_sharedSample;
+ ( Sample *)sharedSample {
   if (_sharedSample==nil) {
      [Sample setSharedSample:_sharedSample];
   }
   return _sharedSample;
}

+ (void)setSharedSample:(Sample *)sample {
   _sharedSample = [[Sample alloc]init];
}
@end

答案 8 :(得分:2)

如果您有许多类级属性,那么单例模式可能是有序的。 像这样:

// Foo.h
@interface Foo

+ (Foo *)singleton;

@property 1 ...
@property 2 ...
@property 3 ...

@end

// Foo.m

#import "Foo.h"

@implementation Foo

static Foo *_singleton = nil;

+ (Foo *)singleton {
    if (_singleton == nil) _singleton = [[Foo alloc] init];

    return _singleton;
}

@synthesize property1;
@synthesize property2;
@synthesise property3;

@end

现在访问您的类级别属性,如下所示:

[Foo singleton].property1 = value;
value = [Foo singleton].property2;

答案 9 :(得分:-3)

[尝试这个解决方案很简单]你可以在Swift类中创建一个静态变量,然后从任何Objective-C类中调用它。