在 Objective-C 协议中定义字符串常量的最佳方法是什么?
我已经定义了我的所有插件都必须实现的协议。我还希望插件都使用某些字符串,例如 MyPluginErrorDomain。对于整数,这很容易在枚举中实现,但我不知道如何对字符串执行相同的操作。通常,在类中,我会
extern NSString * const MyPluginErrorDomain;
在 .h 文件和 .m 文件中定义:
NSString * const MyPluginErrorDomain = @"MyPluginErrorDomain";
但这在协议中效果不佳,因为每个插件都必须提供自己的实现,这违背了拥有一个常数。
然后我尝试了
#define MYPLUGIN_ERROR_DOMAIN @"MyPluginErrorDomain"
,但插件中的实现类似乎看不到#define。谁知道有什么好的解决办法吗?
I have defined a protocol that all my plug-ins must implement. I would also like the plug-ins to all use certain strings, like MyPluginErrorDomain. With integers this is quite easily achieved in an enum, but I can't figure out how to do the same with strings. Normally, in classes I would define
extern NSString * const MyPluginErrorDomain;
in the .h file and in the .m file:
NSString * const MyPluginErrorDomain = @"MyPluginErrorDomain";
but that doesn't work very well in a protocol, because then each plug-in would have to provide its own implementation which defeats the purpose of having a constant.
I then tried
#define MYPLUGIN_ERROR_DOMAIN @"MyPluginErrorDomain"
but the implementing classes in the plug-in can't seem to see the #define. Who knows a good solution?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您保留 .h 定义:
但将此部分放入一个单独的 .m 文件中,该文件包含在您的框架中:
因此插件仍然可以实现该接口,但在编译时它们链接或编译在您的其他 .m 文件中,因此它们将查看
MyPluginErrorDomain
的值。You keep the .h definition:
but put this part into a separate .m file that gets included in your framework:
So plug-ins can still implement the interface but when compiling they link or compile in your other .m file, so they will see the value of
MyPluginErrorDomain
.在 C++ 中,我会在标头中声明它们,如下所示:
请注意,由于指针是 const,因此它们将位于标头 #included 所在的翻译单元的本地,因此不需要使用
extern
来防止多个定义错误。In C++, I would declare them in a header like this:
Note that as the pointers are
const
, they will be local to the translation units the header is #included in, and so there will be no need to useextern
to prevent multiple definition errors.您应该将其实现为外部字符串,如示例所示:
或提供返回静态存储数据的外部函数。例如:
原因是字符串和键经常通过指针值或哈希值来使用和比较,而不是真正的字符串比较(isEqualToString:)。
在实现级别,两者之间存在很大差异:
在代码中,这意味着当比较的字符串在多个二进制文件中定义时:
假设“MyPluginErrorDomain”和“key”具有相同的字符串值,但在不同的二进制文件中定义(即在插件主机中,一个在插件中)。
因此,在许多情况下有必要提供密钥。这似乎是一个微不足道的问题,但很难诊断与差异相关的一些问题。
散列码和指针比较在 Foundation 和其他 objc 技术的内部字典存储、键值编码中使用......如果你的字典直接转为 xml,这是一回事,但运行时使用是另一回事,并且有一些实施和运行时细节中的注意事项。
You should implement it as extern strings as in your example:
or provide extern functions which return static storage data. For example:
The reason is that strings and keys are often used and compared by pointer value or hash value, rather than true string comparison (isEqualToString:).
At the implementation level, there is a big difference between:
In code, that means that when the strings compared are defined in multiple binaries:
Say 'MyPluginErrorDomain' and 'key' have identical string values, but are defined in different binaries (i.e. on in the plugin host, one in the plugin).
It is therefore necessary to provide the keys in many cases. It may seem like a trivial point, but it is hard to diagnose some of the problems associated with the difference.
Hash codes and pointer comparisons are used throughout Foundation and other objc technologies in the internals of dictionary storage, key value coding... If your dictionary is going straight out to xml, that's one thing, but runtime use is another and there are a few caveats in the implementation and runtime details.
您可以在协议的标头中声明它们(但在协议接口本身之外),然后在协议的实现文件中定义它们(显然它不会有
@implementation
部分 - 只是您的NSString
定义)。或者有一个单独的 .h/.m 对,仅用于字符串常量(协议标头可以导入字符串常量标头)。
You can declare them in the header with the protocol (but outside the protocol interface itself), then define them in an implementation file for the protocol (obviously it wouldn't have an
@implementation
section - just yourNSString
definitions).Or have a separate .h/.m pair that is just for the string constants (the protocol header can import the string constants header).