在Cocoa中,Apple经常使用以下范例:
[NSApplication sharedApplication] [NSNotificationCenter defaultNotificationCenter] [NSGraphicsContext currentContext] [NSCalendar currentCalendar]
等等.
他们偶尔也会使用我认为在处理大量代码时更容易辨认的范例.
NSApp //which maps to [NSApplication sharedApplication]
目标
我希望能够在我自己的类中以及对其他类的扩展中使用这种全局变量.
MYClassInstance NSDefaultNotificationCenter NSCal /* or */ NSCurrentCalendar
等等.
“duh”方法
#限定.只需#define NSCal [NSCalendar currentCalendar],但是我们现在都知道,宏是邪恶的(或者他们说的),它似乎不是正确的Cocoa方式.
Apple的方法
我能找到的关于NSApp的唯一来源是APPKIT_EXTERN id NSApp;,这不是完全可重复使用的代码.除非我弄错了,否则所有这些代码都会将NSApp定义为世界各地的id.不幸的是没有帮助.
关闭,但不是很好
在我的搜索中,我设法找到了几个关于“全局常量”的引导,但是这样的事情:
extern NSString * const StringConstant;
遗憾的是,它们仅限于编译时常量,并且无法映射到必要的类方法.
底线
我希望能够推出自己的NSApp样式全局变量,这些变量映射到类[NSNotificationCenter defaultNotificationCenter]等类方法.这可能吗?如果是这样,我应该怎么做呢?
进一步尝试
我试图通过以下方式专门实现框架单例:
MySingletons.h
//... extern id NSNotifCenter; //...
MySingletons.m
//... +(void)initialize { NSNotifCenter = [NSNotificationCenter defaultCenter]; } //...
MyAppDelegate.m
//... #import "MySingletons.h" //... //in applicationDidFinishLaunching: [MySingletons initialize]; NSLog(@"%@",NSNotifCenter); //...
但是,这会导致无法找到_NSNotifCenter符号的编译时错误.
目标!
我目前正在开发一个Objective-C类来封装我在这个问题中提到的一些框架单例.当我拿起它时,我会在这里添加GitHub信息.
解决方法
您只需将包含单例实例的变量公开为全局变量. NSApp实际上并未映射到sharedApplication调用.这是一个普通的旧指针;它是在应用程序启动过程中设置的,指向您从该调用中返回的同一实例.
就像NSApp一样,您为任何导入标头的文件声明变量:
extern MySingleton * MySingletonInstance;
在标题中(如果你愿意,可以使用APPKIT_EXTERN; the docs indicate它只是在ObjC中解析为extern).
在实现文件中,您可以定义变量.通常,保存共享实例的变量被声明为static以限制其与该文件的链接.如果删除静态,则语句定义标题中“重新声明”的存储.
然后,像以前一样使用它.唯一需要注意的是,在第一次使用全局之前,你仍然必须调用你的单例设置方法[MySingleton sharedInstance],以确保它被初始化. -applicationDidFinishLaunching:可能是一个很好的候选人.
至于创建指向框架单例的指针,你可以在任何你喜欢的变量中隐藏[CocoaSingleton sharedInstance]的结果:一个想要使用它的类中的ivar,一个局部变量,或者你很早就初始化的全局变量在您的程序中通过您编写的功能.
问题是,不能保证不会引起问题.除了在NSApp的情况下(或者除非在某处记录),实际上并不能保证从任何给定的sharedInstance调用中返回的对象将在调用堆栈结束后保持活动,有效或有用.
这可能只是偏执狂,但我建议不要这样做,除非你能在某个地方找到一个保证,你感兴趣的假想单身人士总会返回相同的实例.否则,你可能会突然得到一个悬空的全局指针.
解决代码问题时,标题中的声明不会创建变量.你还需要一个定义:
// MySingletons.h // Dear compiler,There exists a variable,NSNotifCenter,whose // storage is elsewhere. I want to use that variable in this file. extern id NSNotifCenter;
// MySingletons.m // Dear compiler,please create this variable,reserving memory // as necessary. id NSNotifCenter; @implementation MySingletons // Now use the variable. // etc.
如果你正在创建一个单身人士,你可能想看一眼Apple’s singleton documentation.