我正在使用一组Constant.m
个文件,每个目标一个,为每个目标定义特定内容。例如:
// Constants.h
extern NSString * const kDatabaseFileName;
//Constants.m
NSString * const kDatabaseFileName = @"target_one.sqlite";
我还想为每个目标定义一个NSArray:
NSArray * const kLabelNames = [[NSArray alloc] initWithObjects:
@"nameLabel", @"addressLabel", nil];
但是这给出了“错误:初始化元素不是常数”。使用'arrayWithObjects`也不起作用。这是因为我的数组中的字符串不是常量吗?
如何将数组设置为全局常量?感谢。
答案 0 :(得分:28)
在Objective-C中,对象只能在堆中分配,因此无法在静态内存中创建NSArray。但是,您可以创建一个指向NSString常量的C数组,如此...
NSString * const kLabelNames[] = {
@"Foo", @"Bar", @"Baz"
};
...然后你可以编写像这样的类方法......
+ (NSArray *)labelNames
{
static NSArray *names;
if (names == nil) {
names = [[NSArray alloc] initWithObjects:kLabelNames count:3];
}
return names;
}
修改强>
请注意,随着ARC,Grand Central Dispatch等新技术的引入以及数组的新文字语法,现在有一种更简单的方法可以实现类似的功能。请注意,下面的示例还提供了更高的线程安全性,尽管原始示例可能包含@synchronized
块或其他几种机制之一,以实现类似的结果。
+ (NSArray *)labelNames
{
static NSArray *names;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
names = @[@"Foo", @"Bar", @"Baz"];
});
return names;
}
然而,上述示例并未完全解决原始问题。如果确实需要一个全局常量数组,前面的例子可以像原始答案一样重写,同时仍然利用GCD:
NSString * const kLabelNames[] = {
@"Foo", @"Bar", @"Baz"
};
+ (NSArray *)labelNames
{
static NSArray *names;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
names = [NSArray arrayWithObjects:kLabelNames count:3];
});
return names;
}
答案 1 :(得分:6)
如果你想要一组包含NS类型的常量,可以考虑将它们全部放在一个单例中。
您可以拥有一个头文件和多个实现文件(每个目标一个)。只要这一切都实现了头文件中声明的类,你应该没问题。
答案 2 :(得分:6)
这是一个更简单的方法:
使用逗号分隔的元素(或您想要的任何分隔符)声明NSString
NSString *const kLabelNames = @"Foo,Bar,Baz";
然后在需要时转换为NSArray:
NSArray *namesArray = [kLabelNames componentsSeparatedByString:@","];
答案 3 :(得分:5)
使用宏:
#define SOME_ARRAY (@[@"blah", @"asdf", @"qwerty"])
答案 4 :(得分:2)
您应该创建一个包含类方法中常量的类。然后,您可以将类添加到任何目标,并调用方法以获取对象(如数组)中的常量。改变类或类实现来改变常量的返回。
如果您经常使用它,您可以创建一个定义方法名称的协议。然后换出在每个目标中实现协议的类,以便相同的代码根据需要返回不同的值。
答案 5 :(得分:1)
如果要避免对每次使用进行NULL检查,可以继承NSObject + initialize方法。这将被调用一次,第一次实例化您的类(如果任何子类被实例化,则每个子类再次调用),并且是进行此类初始化的非常好的地方。