Iphone +;(无效)未调用初始化(目标C)
我的方法+(void)initialized没有被调用,我对Objective C非常陌生。代码在iPhone游戏开发书中,我必须显式调用该方法才能工作。.m文件中的代码是:Iphone +;(无效)未调用初始化(目标C),iphone,objective-c,Iphone,Objective C,我的方法+(void)initialized没有被调用,我对Objective C非常陌生。代码在iPhone游戏开发书中,我必须显式调用该方法才能工作。.m文件中的代码是: ResourceManager *g_ResManager; @implementation ResourceManager //initialize is called automatically before the class gets any other message, per from http://sta
ResourceManager *g_ResManager;
@implementation ResourceManager
//initialize is called automatically before the class gets any other message, per from http://stackoverflow.com/questions/145154/what-does-your-objective-c-singleton-look-like
+ (void) initialize
{
static BOOL initialized = NO;
if(!initialized)
{
initialized = YES;
g_ResManager = [[ResourceManager alloc] init];
}
}
...
@end
但在.h文件中,会对变量进行外部声明:
extern ResourceManager *g_ResManager; //paul <3's camel caps, hungarian notation, and underscores.
@interface ResourceManager : NSObject {
...
}
...
@end
外部资源管理器*g\u ResManager//paul来自NSObject的文档:
运行时将初始化发送到每个
只在程序中初始化一次
就在上课之前,或者任何一节课之前
从它继承的,被发送它的
来自程序内部的第一条消息。
(因此,该方法可能永远不会被调用
如果未使用该类。)运行时
将初始化消息发送到
以线程安全的方式初始化。
超类收到此消息
在它们的子类之前
+initialize
仅在发送类(它是第一条消息)之前调用。在向类发送消息之前,不会调用+initialize
方法
例如:
如果调用[[MyObject alloc]init]
,+initialize
在将alloc
发送到MyObject之前,对MyObject调用+initialize
。+initialize
直到您向类的实例发送一些消息时才会调用。你发信息了吗
一个可能的问题可能是您从代码的另一部分向g_ResManager发送了一条消息?
这行不通,因为:
g_ResManager
在启动时为零
您向g\u ResManager
发送一条消息,即nil
Objective-C运行时算作“向类发送消息”的不是它在源代码中的语法外观,而是真正的对象和发送的消息
因此,在本例中,nil
获取消息,nil
不是ResourceManager
的实例,因此也不会调用+initialize
我会把你的代码修改如下:首先,在.m中
static ResourceManager *g_ResManager;
@implementation ResourceManager
//initialize is called automatically before the class gets any other message
+ (void) initialize
{
static BOOL initialized = NO;
if(!initialized)
{
initialized = YES;
g_ResManager = [[ResourceManager alloc] init];
}
}
+(ResourceManager*)sharedResourceManager
{
return g_ResManager;
}
...
@end
然后在h,我会
@interface ResourceManager:NSObject {
...
}
+(ResourceManager*)sharedResourceManager
@end
然后,您可以始终使用[ResourceManager sharedResourceManager]
事实上,正如Rob在评论中所说,在这种情况下,您可以完全取消+初始化
。我改成
@implementation ResourceManager
+(ResourceManager*)sharedResourceManager
{
static ResourceManager *g_ResManager=nil;
if(!g_ResManager){
g_ResManager=[[ResourceManager alloc] init];
}
return g_ResManager;
}
...
@end
这是我个人经常使用的成语。但我警告你,这不是完全线程安全的!只要在生成线程之前调用[ResourceManager sharedResourceManager]
一次就可以了,我几乎总是这样做,但这是需要记住的一件事。另一方面,由于+initialize
定义良好的行为,上面使用+initialize
的版本应该是线程安全的。请参阅中的讨论。请注意,当您不自己分配对象时,应该保留它。例如:
+ (NSPredicate *)somePredicate
{
static NSPredicate *predicate = nil;
if (!predicate) {
predicate = [NSPredicate predicateWithFormat:@"status == 2"];
[predicate retain];
}
return predicate;
}
否则它将无法存活足够长的时间,无法使用几次(指针仍然是!nil
,但不再有效)。这正是发生的情况。非常感谢!!!我来自Java,在这种情况下总是得到一个NullPointerException:D再次感谢!很高兴知道它起作用了。不管怎么说,它只是表明有那么多蹩脚的iPhone编程书是由没有经验的人写的。没有一个理智的Obj-C开发人员会制造这样一个全局外部实例变量。制作一个+sharedFoo
返回共享实例是一种习惯用法。请告诉我。这真的很有道理。使用单例模式并声明一个外部变量。但因为我对Objective-C的知识水平较低,所以就这样离开了。现在一切都好了。没有外部变量了。再次感谢。关于+initialize的工作原理,Yuji是绝对正确的,但是这里不需要使用+initialize。只要在+sharedResourceManager中初始化g_ResManager(如果为零)。在这种情况下,您甚至可以将g_ResManager设置为静态函数;不需要文件static.extern实际上是旧C语言的遗留。正如您所见,除非您必须与基于C的库交互,否则在Objective-C中应该避免使用它。也谢谢您的回答,Jasarien。这是真的,但它不是问题的答案。好的,我应该对此发表评论。抱歉。@EricGoldberg此方法不拥有保留值;它存储在一个静态变量中。这是正确的代码。