3

我想在 Cocoa 中有一个静态变量。

在查看了如何在 Objective-C 中声明类级属性?,我不清楚我迄今为止一直在做的事情是否有问题,即

// Foo.m
static NSString* id;
@interface Foo ()

代替

// Foo.h
@interface Foo {
}

+(NSString*) id;

// Foo.m
+(NSString*) id
{
  static NSString* fooId = nil;

  if (fooId == nil)
  {
    // create id
  }

  return fooId;
}

显然,第二种方法提供了初始化 id 的机会。但是,如果我在代码中的其他地方自己初始化 id,在里面,比如说一个 getter:

-(NSString*) getId
{
    if (id==nil) {
      id =  ... // init goes here
    }
    return id;
}

那么与更复杂的类函数方法相比,简单的静态声明方法有什么问题吗?我错过了什么?

4

1 回答 1

7

首先,你要求的是一个全局变量,一个静态的类似但有点不同......

static声明放在头 () 文件中的任何内容之外,@interface将在您包含头文件的每个实现 ( ) 文件中.h创建不同.m的变量——在这种情况下,这不是您想要的。

因此static,在声明中创建一个变量,其生命周期是整个应用程序执行的生命周期,但仅在它出现的编译单元(例如实现文件)中可见- 直接或通过包含。

要创建一个在任何地方都可见的全局变量,您需要extern在标题中使用:

extern NSString *id;

并在您的实现中重复声明而不使用extern

NSString *id;

至于全局变量与类方法有什么问题,这是程序设计和可维护性的问题。这里只是需要考虑的几点:

  • 使用方法时,除非您提供 setter 方法和 getter 方法,否则无法更改值。变量始终是可读写的。
  • 命名空间污染:类方法只有与类名( )配对时才有效[YourClass id];变量名在任何包含它的地方都是有效的id;这既污染了名称空间,又失去了和之间的联系id——YourClass这导致我们......
  • 封装:全局变量打破了强封装,封装有助于程序设计和维护——这是一个很大的话题。

也就是说,全球人可能有时间和地点,有时......

问题更新后

在实现中声明的static变量实际上是一个“类变量”——一个由类的所有实例共享的变量。

类变量与 setter 和 getter 类方法的优缺点与实例变量与属性和 setter/getter 实例方法的优缺点完全相同。

类 setter/getter 允许在每次读/写时执行验证和其他逻辑;和内存管理的本地化——简而言之,任何方法的抽象和封装优势。

因此,您使用变量还是 setter/getter 取决于您的应用程序。这与您使用实例变量还是 setter/getter/property 是同一个问题。

于 2012-10-05T01:43:25.233 回答