我已经定义了一个我的所有插件必须实现的协议。我也希望所有插件都使用某些字符串,比如MyPluginErrorDomain。使用整数这很容易在枚举中实现,但我无法弄清楚如何用字符串做同样的事情。通常,在课程中我会定义
extern NSString * const MyPluginErrorDomain;
<。>在.h文件和.m文件中:
NSString * const MyPluginErrorDomain = @"MyPluginErrorDomain";
但是这在协议中不能很好地工作,因为每个插件都必须提供自己的实现,这违背了具有常量的目的。
然后我尝试了
#define MYPLUGIN_ERROR_DOMAIN @"MyPluginErrorDomain"
但是插件中的实现类似乎看不到#define。谁知道一个好的解决方案?
答案 0 :(得分:10)
您可以使用协议在标头中声明它们(但在协议接口本身之外),然后在协议的实现文件中定义它们(显然它没有@implementation
部分 - 只是您的{ {1}}定义)。
或者有一个单独的.h / .m对,它只适用于字符串常量(协议头可以导入字符串常量标题)。
答案 1 :(得分:9)
你保留.h定义:
extern NSString * const MyPluginErrorDomain;
但将此部分放入一个单独的.m文件中,该文件包含在您的框架中:
NSString * const MyPluginErrorDomain = @"MyPluginErrorDomain";
所以插件仍然可以实现界面,但是在编译时,它们会在你的其他.m文件中链接或编译,所以他们会看到MyPluginErrorDomain
的值。
答案 2 :(得分:3)
在C ++中,我会在这样的标题中声明它们:
const char * const MYPLUGIN_ERROR_DOMAIN = "MyPluginErrorDomain";
const char * const MYPLUGIN_FOO_DOMAIN = "MyPluginFooDomain";
请注意,由于指针是const
,因此它们将是标头为#included的翻译单元的本地,因此不需要使用extern
来防止多个定义错误。
答案 3 :(得分:2)
您应该将其实现为extern字符串,如示例所示:
extern NSString * const MyPluginErrorDomain;
或提供返回静态存储数据的extern函数。例如:
/* h */
extern NSString * MyPluginErrorDomain();
/* m */
NSString * MyPluginErrorDomain() {
static NSString * const s = @"MyPluginErrorDomain";
return s;
}
原因是字符串和键经常被指针值或散列值使用和比较,而不是真正的字符串比较(isEqualToString :)。
在实施层面,:
之间存在很大差异在代码中,这意味着当比较的字符串在多个二进制文件中定义时:
说'MyPluginErrorDomain'和'key'具有相同的字符串值,但是在不同的二进制文件中定义(即插件主机中的插件,插件中的一个)。
/////// Pointer comparison (NSString)
BOOL a = [MyPluginErrorDomain isEqualToString:key];
BOOL b = MyPluginErrorDomain == key;
// c may be false because a may be true, in that they represent the same character sequence, but do not point to the same object
BOOL c = a == b;
/////// Hash use (NSString)
// This is true
BOOL d = [MyPluginErrorDomain hash] == [key hash];
// This is indicative if true
BOOL e = [MyPluginErrorDomain hash] == [someOtherStringKey hash];
// because
BOOL f = [MyPluginErrorDomain isEqualToString:someOtherStringKey];
// g may be false (though the hash code is 'generally' correct)
BOOL g = e == f;
因此,在许多情况下需要提供密钥。这似乎是一个微不足道的观点,但很难诊断出与这种差异相关的一些问题。
散列代码和指针比较在整个Foundation和其他objc技术中用于字典存储的内部,键值编码......如果你的字典直接用于xml,这是一回事,但运行时使用是另一个,那里在实现和运行时细节中有一些注意事项。