Objective-C 覆盖[NSObject初始化]是否安全?
基本上,我有以下代码(此处解释:协议中的 Objective-C 常量)
// MyProtocol.m
const NSString *MYPROTOCOL_SIZE;
const NSString *MYPROTOCOL_BOUNDS;
@implementation NSObject(initializeConstantVariables)
+(void) initialize {
if (self == [NSObject class])
{
NSString **str = (NSString **)&MYPROTOCOL_SIZE;
*str = [[MyClass someStringLoadedFromAFile] stringByAppendingString:@"size"];
str = (NSString **)&MYPROTOCOL_BOUNDS;
*str = [[MyClass someStringLoadedFromAFile] stringByAppendingString:@"bounds"];
}
}
@end
我想知道:拥有一个覆盖 NSObject 的 +initialize
方法的类别对我来说安全吗?
Basically, I have the following code (explained here: Objective-C Constants in Protocol)
// MyProtocol.m
const NSString *MYPROTOCOL_SIZE;
const NSString *MYPROTOCOL_BOUNDS;
@implementation NSObject(initializeConstantVariables)
+(void) initialize {
if (self == [NSObject class])
{
NSString **str = (NSString **)&MYPROTOCOL_SIZE;
*str = [[MyClass someStringLoadedFromAFile] stringByAppendingString:@"size"];
str = (NSString **)&MYPROTOCOL_BOUNDS;
*str = [[MyClass someStringLoadedFromAFile] stringByAppendingString:@"bounds"];
}
}
@end
I was wondering: Is it safe for me to have a category that overrides the NSObject's +initialize
method?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
简而言之,不,您无法在类的类别中安全地实现
+initialize
方法。您最终将替换现有的实现(如果有),并且如果一个类的两个类别都实现了 +initialize,则无法保证哪一个会被执行。+load
具有更可预测和定义明确的行为,但发生得太早而无法做任何有用的事情,因为很多事情都处于未初始化状态。就我个人而言,我完全跳过
+load
或+initialize
并使用编译器注释来导致在加载底层二进制文件/dylib 时执行函数。不过,此时您能安全地做的事情仍然很少。您最好根据启动的应用程序进行初始化。
NSApplication
和UIApplication
都提供委托/通知挂钩,用于在应用程序启动时向应用程序注入一些代码。In short, no, you cannot safely implement
+initialize
methods in categories on classes. You'll end up replacing an existing implementation, if there is one, and if two categories of one class both implement+initialize
, there is no guarantee which will be executed.+load
has more predictable and well-defined behavior, but happens too early to do anything useful because so many things are in an uninitialized state.Personally, I skip
+load
or+initialize
altogether and use a compiler annotation to cause a function to be executed on load of the underlying binary/dylib. Still, there is very little you can do safely at that time.You are far better off doing your initialization in response to the application being brought up.
NSApplication
andUIApplication
both offer delegate/notification hooks for injecting a bit of code into the app as it launches.为什么不在 MyClass 类中设置这两个变量呢?另外,为什么不使用访问器?最好在实际使用它的类上定义一个访问器,而不是使用一个不知从何而来的假常量。一个简单的 +(NSString *)myProtocolSize;即使在协议中也会做得很好。
此外,重写类别中类的方法“有效”,但不可靠,应不惜一切代价避免:如果您要重写的方法是在类别中实现的,则运行时不保证加载顺序和您的实现可能永远不会被添加到其中。
Why don't you setup those two variables inside the class MyClass instead ? And also, why don't you use accessors ? Instead of having a fake constant variable that comes from nowhere, it's preferable to define an accessor on a class that should actually use it. A simple +(NSString *)myProtocolSize; would do great, even in the protocol.
Also, overriding methods of a class in a category "works" but isn't reliable and should be avoided at all cost: if the method you're overriding is implemented in a category, the runtime does NOT guarantee the loading order and your implementation might never be added to it.
假设我们暂时忽略 C++ 的异常情况,
NSString *const
类型的变量将始终在代码运行之前进行初始化:const NSString *
类型的变量(const NSString *
>const 关键字应用于 NSString 的内部,而不是其地址)可以由任何代码修改,但不能向其发送消息。它违背了使其成为 const 的目的。考虑使用全局函数:或者使用类方法:
您之前问过一个关于为什么您的
const
字符串不接受动态值的问题 - 这是因为您似乎不了解const
对符号起作用。您应该阅读 C 语言中const
关键字的含义,并且如果const
不正确,则应该考虑另一种获取字符串的方法。A variable of type
NSString *const
will always be initialized before your code runs, assuming we ignore C++ vagaries for the moment:A variable of type
const NSString *
(theconst
keyword applying to the guts of theNSString
, not its address) can be modified by any code, but cannot have messages sent to it. It defeats the purpose of making itconst
. Consider instead a global function:Or use a class method:
You asked a question earlier about why your
const
strings wouldn't accept dynamic values--this is because you do not seem to understand whatconst
does to a symbol. You should read up on the meaning of theconst
keyword in C and should look at another approach to getting your strings ifconst
is not the right one.