静态NSMutableArray和多线程用法的含义

时间:2014-01-26 15:48:59

标签: objective-c

以下代码究竟是static做了什么,我应该何时或更好地使用Static

// Returns an array of 30 odd numbers
- (NSArray *)odds
{
static NSMutableArray *odds;
odds = [[NSMutableArray alloc] init];
int i = 1;
while ([odds count] < 30) {
[odds addObject:[NSNumber numberWithInt:i]];
i += 2;
}
return odds;
}

2 个答案:

答案 0 :(得分:8)

您问题中的代码最初是

- (NSArray *)odds
{
    static NSMutableArray *odds = [[NSMutableArray alloc] init];
    // ... fill array ...
    return odds;
}

并且您在(现已删除)评论中说,您在“大书呆子牧场指南”中找到了该代码。

那么,该指南有一个错误。

程序的生命周期中存在静态局部变量,但仅可见 在声明它的函数内部。变量的值保留在之间 重复的函数调用。

在C和Objective-C中,静态局部变量只能用编译时初始化 因此,

static NSMutableArray *odds = [[NSMutableArray alloc] init];

无效。 (顺便说一下,C ++中不存在这种限制。因此,上述代码在Objective-C ++中是有效的,虽然没有意义。)

那么如何解决这个问题呢? 方法1:(最简单的解决方案。)删除static

- (NSArray *)odds
{
    NSMutableArray *odds = [[NSMutableArray alloc] init];
    // ... fill array ...
    return odds;
}

现在odds是一个普通的局部变量,每次都会创建并填充数组 当函数被调用时。

方法2:当第一次调用该方法时,静态变量只能用于创建和填充数组一次。 那看起来像是:

- (NSArray *)odds
{
    static NSMutableArray *odds = nil;
    if (odds == nil) { // Check if array has already been initialized or not.
        odds = [[NSMutableArray alloc] init];
        // ... fill array ...
    }
    return odds;
}

函数“记住”变量的值,所以在调用函数时 第二次,它返回现有数组,不会创建新数组。

方法3:仅初始化一次内容的“现代”方法是使用GCD函数dispatch_once()

- (NSArray *)odds
{
    static NSMutableArray *odds;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        odds = [[NSMutableArray alloc] init];
        // ... fill array ...
    });
    return odds;
}

这具有线程安全的额外优势。

答案 1 :(得分:3)

马丁所说的(在#3中),但有更多的迂腐:

- (NSArray *)odds
{
    static NSArray *odds;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSMutableArray *temp = [[NSMutableArray alloc] init];
        // ... fill temp ...
        odds = [temp copy];
    });
    return odds;
}

通过在这里创建该可变数组的不可变副本,这意味着任何调用copy的调用者都将免费获得该副本(以及保留计数的成本),而复制可变数组是(相对)昂贵。它还可以加强代码,防止调用者改变返回的数组。永远不应该发生,但确实如此。