以下代码究竟是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;
}
答案 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
的调用者都将免费获得该副本(以及保留计数的成本),而复制可变数组是(相对)昂贵。它还可以加强代码,防止调用者改变返回的数组。永远不应该发生,但确实如此。