我的方法+(void)初始化没有被调用,我在Objective C中是非常新的。代码在iPhone游戏开发的书中,我必须明确地调用该方法才能工作。 .m文件中的代码是:
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
我尝试了所有内容(删除外部,在.m声明中放置静态)并始终遇到编译错误。上面的代码编译但是从不调用方法初始化(推断断点以查看)。
一些线索?
答案 0 :(得分:14)
+initialize
。你发了消息吗?
一个可能的问题可能是您从代码的其他部分向g_ResManager
发送了邮件?
那是行不通的,因为:
g_ResManager
在发布时为零。g_ResManager
发送了一条消息,nil
。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在评论中所说,在这种情况下,你可以完全取消+initialize
。将.m更改为类似
@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
的上述版本应该是线程安全的。请参阅this blog post中的讨论。
答案 1 :(得分:6)
来自NSObject的文档:
运行时将initialize发送给每个 一个程序中的类恰好一次 就在课前,或任何课程 继承自它,发送它 来自程序内的第一条消息。 (因此可能永远不会调用该方法 如果没有使用该类。)运行时 发送初始化消息 类以线程安全的方式。 超类收到此消息 在他们的子类之前。
+initialize
仅在您发送第一条消息之前调用。在向课程发送消息之前,不会调用+initialize
方法。
例如:
如果您致电[[MyObject alloc] init];
,则会在+initialize
发送至MyObject之前在MyObject上调用alloc
。
答案 2 :(得分:0)
请注意,如果您不自行分配对象,则应保留它。例如:
+ (NSPredicate *)somePredicate
{
static NSPredicate *predicate = nil;
if (!predicate) {
predicate = [NSPredicate predicateWithFormat:@"status == 2"];
[predicate retain];
}
return predicate;
}
否则它的存活时间不足以使用几次(指针仍为!nil
,但不再有效。)