【问题标题】:Objective-c static NSArray initializerObjective-c 静态 NSArray 初始化器
【发布时间】:2012-10-30 14:38:34
【问题描述】:

我有这段代码(大部分的一小部分 - 只是这里显示的麻烦部分):

#define kSizeLarge @"large"

-(void)determineBestFileSizeWithLimit:(int)limit
{
    static NSString *largeName = kSizeLarge;
    static NSArray *nameArray = @[kSizeLarge];
    ...
}

编译器喜欢第一个静态变量,讨厌第二个,说

Initializer element is not a compile-time constant

从第二行删除静态使编译器高兴。

我做错了什么或做错了什么?

【问题讨论】:

  • 好的,我现在明白了:那些集合静态初始化器实际上只是代码等效的简写 - @[a,b,c] 实际上只是 [NSArray arrayWithObjects:a,b,c,nil] 的简写,因为这不是编译时常量,速记版本也不是。
  • @CubsFanRon:不完全是。数组字面量相当于调用arrayWithObjects:count: 方法

标签: objective-c ios literals


【解决方案1】:

当你的静态变量的初始化器不是编译时常量时,你需要使用另一种初始化机制,比如dispatch_once:

-(void)determineBestFileSizeWithLimit:(int)limit {
    static NSString *largeName = kSizeLarge;
    static NSArray *nameArray = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        nameArray = @[kSizeLarge];
    });
}

【讨论】:

  • @Joe 是的,当每个人都按照 Apple 的指导方针建模他们的代码时就会发生这种情况 :) 我不断从我的 earlier answers 之一复制 dispatch_once sn-p,所以 onceToken 保持不变.不过,这个特殊的问题是“快速打字比赛”:)
  • 谢谢。感觉它应该是一个编译时常量,因为所有 is 在编译时都是常量和已知的,但我想它不是。我试图避免额外的代码来管理它的静态性(这是一个词?)。
  • 哦,我将这个标记为“答案”只是因为它是第一个,而不是因为它比另一个响应或多或少正确(因为它们是相同的)。
  • @CubsFanRon 其实我是第一个,只有几秒钟,但这很好:)
  • 这不是说每次调用这个方法都要对onceToken进行检查吗?
【解决方案2】:

NSArray 文字不是您发现的编译时常量。您应该使用dispatch_once 来初始化数组。

#define kSizeLarge @"large"

-(void)determineBestFileSizeWithLimit:(int)limit
{
    static NSString *largeName = kSizeLarge;
    static NSArray *nameArray = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        nameArray = @[kSizeLarge];
    });
    ...
}

【讨论】:

  • 我并没有真正挖掘“dispatch_once”模型 - 例如,我发现它不像 if (!nameArray) {nameArray = @[@kSizeLarge];} 那样清晰
  • 这不是线程安全的,dispatch_once 只比您喜欢的多增加 1 行代码。任何熟悉 Objective-C 的人都应该具备 GCD 和块的基本知识,如果他们还没有学习的话。
  • 我并不真正关心将代码行作为衡量标准——我更关心的是“代码的含义”作为模因。我的代码简单直接,但由于它有这个潜在的缺陷等着我,我想我会学习一个新的模因。然后这个新代码将在我的脑海中变得简单直接,这是我所关心的。
  • 让我进一步测试我的理解:如果我有一个静态变量,要么仅限于文件范围或函数/方法范围,如果它具有非编译时值,我应该使用 @ 987654326@ 方法来初始化它。我是否也应该对非静态变量(例如属性)执行此操作,尤其是那些通过惰性实例化创建的变量?
  • 不,不要将它用于非静态变量,因为它们只会在第一次运行时被分配。您应该使用它来初始化任何静态非编译时常量是正确的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-24
相关资源
最近更新 更多