【问题标题】:Declaring static variables in cocoa在可可中声明静态变量
【发布时间】:2012-10-04 17:54:41
【问题描述】:

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

看了How do I declare class-level properties in 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;
}

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

【问题讨论】:

    标签: cocoa class variables static


    【解决方案1】:

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

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

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

    要创建一个随处可见的全局变量,您需要在标题中使用extern

    extern NSString *id;
    

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

    NSString *id;
    

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

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

    也就是说,全局变量可能有时间和地点,有时......

    问题更新后

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

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

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

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

    【讨论】:

    • 但是你不能同时提供在方法级静态变量上操作的getter和setter方法;这两种方法都可以有同名的静态变量,但它们是不同的东西。
    • 如果你在类接口文件中使用编译单元级的静态变量,是不是确定类方法使用的静态变量总是同一个变量,而实现文件#导入该类的接口文件实际上设置了具有相同名称但不同的静态变量?似乎应该是这样,因为类实现可能是与导入其接口的其他实现分开编译的;但我很想知道。
    • @echristopherson - 正确,方法级静态变量在声明它们的方法中的可见性受到限制。基于变量的类级 setter 和/或 getter 方法将对类级静态变量进行操作。在任何方法或函数之外的实现文件中声明的任何静态变量都是类级静态变量 - 相当于某些其他语言中的“类变量”。将此类声明置于 @implementation 块(以及该块中的所有其他内容之外)的逻辑位置,以使其在视觉上清楚地属于该类。
    • @echristopherson - re:头文件中的编译单元级静态变量 - 是的,在包含头文件的每个编译单元中都会创建一个 distinct 变量。静态变量声明在头文件相当晦涩,你会(或应该!)很少遇到它们。
    • 首先,我很抱歉。我的意思是静态变量,是为了显示在 m 文件中分配的静态变量,而不是像我的评论建议的那样在 h 文件中。我正在更正我原来的帖子。我了解全局变量的缺点,并且只对我在帖子中介绍的两种方法的区别感兴趣。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多