// constants.h
extern NSArray const *testArray;
// constants.m
NSArray const *testArray = [NSArray arrayWithObjects: @"foo", @"bar", nil];
我遇到的错误是
初始化元素不是常数
或者如果我去掉指针标识符(*),我会得到:
'NSArray' 的静态分配实例
// constants.h
extern NSArray const *testArray;
// constants.m
NSArray const *testArray = [NSArray arrayWithObjects: @"foo", @"bar", nil];
我遇到的错误是
初始化元素不是常数
或者如果我去掉指针标识符(*),我会得到:
'NSArray' 的静态分配实例
简而言之,你不能。除了NSString以外,Objective-C对象只能在运行时创建。因此,你不能使用表达式来初始化它们。
有几种方法可以解决这个问题。
(1) 不带const
关键字声明NSArray *testArray
,然后编写一小段代码,在应用程序生命周期的早期阶段设置该值。
(2) 声明一个方便的类方法来返回数组,然后在该方法内部使用static NSArray *myArray
并将其视为单例(在SO上搜索"objective-c singleton",大约会得到无数个如何实例化的答案)。
@[...]
语法糖,这仍然是正确的,对吗? - Ben Mosher可能有些晚了,但是如果您在程序运行过程中不修改值,并且只涉及字符串,那么您可以通过使用 C
数组来声明您的数组,方法如下:
extern NSString * const MY_CONSTANT_STRING_ARRAY[];
在你的constants.h
文件中,然后在你的constants.m
文件中,你可以像这样添加对象:
NSString * const MY_CONSTANT_STRING_ARRAY[] = { @"foo", @"bar" };
然后要访问成员,你可以使用类似下面这样的for循环,带有C sizeof()运算符:
显然,这是一个C数组,而不是NSArray,所以您没有所有附加的有趣方法,例如objectAtIndex:,因此您可以在程序中的某个位置创建一个辅助函数,使用我上面概述的方法循环遍历所有字符串,并返回一个NSArray(甚至是NSMutableArray)。但是,如果您像我一样只需要在整个程序中使用NSString值的常量数组,则此方法效果最佳。
这样做将所有字符串数组常量封装在constants.h中,并且通过在.pch文件中添加constants.h而在整个程序中仍然可用,而不是为此数组创建单例或使用一些代码设置数组,这有点违反了constants文件的目的,因为它将实际的常量从constants文件中移除了。
根据@JesseGumpo的评论进行编辑:
由于使用sizeof()来确定数组的大小可能会出现问题,一个简单的解决方法是在您的常量文件中声明数组的大小,如下所示:
//.h
extern int SIZE_OF_MY_CONSTANTS_ARRAY;
///.m
int SIZE_OF_MY_CONSTANTS_ARRAY = 2;
然后在for循环中访问成员可以像这样:
for (int i=0; i < SIZE_OF_MY_CONSTANTS_ARRAY; i++)
NSLog(@"my constant string is: %@", MY_CONSTANT_STRING_ARRAY[i]);
是的,这种方法不能动态捕获数组的大小,但如果您在常量文件中声明一个数组,那么您已经从一开始就知道该数组的大小,因此即使它增加了两行代码,它仍然可以实现将数组放在常量文件中。
如果有人有更多建议或熟悉其他 C 技巧,请在下面留言!
sizeof()
。我将编辑我的答案以反映我的最终方法,由于它使用简单数据类型,仍然可以工作并完成在常量文件中拥有一个数组的任务。 - AngeloS#define STATIC_ARRAY(x, ...) \
static NSArray* x=nil; \
static dispatch_once_t x##onceToken; \
dispatch_once(&x##onceToken, ^{ x = @[ __VA_ARGS__ ]; });
使用示例
STATIC_ARRAY(foo, @"thing1", @"thing2", [NSObject new]);
#define arrayTitle [NSArray arrayWithObjects: @"hi",@"foo",nil]
希望这可以帮到你。arrayTitle
时,它并没有提供一个恒定的数组,而是生成一个新数组。请注意,翻译尽可能保留原意,以通俗易懂为目标。 - AbizernarrayTitle
,它都会分配一个新的数组实例并填充对象。这是完全不必要的大量分配流量。 - bbum对我来说,以下常量数组的实现方式更方便
static NSString * kHeaderTitles [3] = {@ "ACCOUNT DETAILS", @ "SOCIAL NETWORK", @ "SETTINGS"};
static int kNumbers[3] = {1, 2, 3};
#define arrayOfStrings @[@"1", @"2", @"3", @"4"]
#define arraysOfIds @[@(1), @(2), @(3), @(4)]
基本上,当你在代码中调用arrayOfStrings时,它被替换为@[@"1", @"2", @"3", @"4"],并且同样的情况也适用于arraysOfIds。
arrayOfStrings
或arraysOfIds
时,这也会导致一个新的数组实例被创建。 - bbum