objective-c - 类方法的全局变量

标签 objective-c cocoa macros global-variables class-method

背景

在 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 方法来解决这个问题.

苹果的方法

我能找到的关于 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的信息等我上来的时候再补充上。

最佳答案

这很有趣,我 just made this suggestion关于另一个问题。

您只需将保存单例实例的变量公开为全局变量本身。 NSApp 实际上不是 映射sharedApplication 调用。这是一个普通的旧指针;它是在应用程序启动过程中设置的,指向您将从该调用返回的同一实例。

就像 NSApp 一样,您可以为导入 header 的任何文件声明变量:

extern MySingleton * MySingletonInstance;

在 header 中(您可以根据需要使用 APPKIT_EXTERNthe docs indicate 它只是在 ObjC 中解析为 extern)。

在实现文件中定义变量。通常持有共享实例的变量被声明为 static 以限制它与该文件的链接。如果您删除 static,该语句定义 header 中“重新声明”的存储。

然后,像以前一样使用它。唯一需要注意的是,您仍然必须在第一次使用全局变量之前调用您的单例设置方法 [MySingleton sharedInstance] 以确保它已初始化。 -applicationDidFinishLaunching: 可能是执行此操作的理想选择。

至于创建指向框架单例的指针,您可以将 [CocoaSingleton sharedInstance] 的结果存储在您喜欢的任何变量中:一个想要使用它的类中的 ivar,一个局部变量,或者在您通过编写的函数在程序的早期初始化的全局变量中。

问题是,这不能保证不会引起问题。除了 NSApp 的情况(或者除非它被记录在某处),真的不能保证你从任何给定的调用返回的对象 sharedInstance 将保持活跃,有效,或者在调用堆栈末尾有用。

这可能只是偏执狂,但我建议不要这样做,除非你能在某个地方找到保证你感兴趣的假定单例总是返回相同的实例。否则,您可能会突然得到一个悬空的全局指针。

针对您的代码, header 中的声明不会创建变量。你仍然需要在某处定义:

// 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 .

关于objective-c - 类方法的全局变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8498754/

相关文章:

objective-c - 将 NSString 与 AVAudioPlayer 一起使用

ios - 实现 NSURLConnection 委托(delegate)

arrays - 这是实现 NSImage 数组的合适方法吗?

C预处理器: How can I disable #error macro?

c++ - 为什么 va_start 会失败?

ios - 在iOS 6.0中找不到AVAudioPlayer

ios - UIPageViewController 防止在滚动时隐藏键盘

cocoa - 在 Interface Builder 中设置操作时控制拖动操作方向的重要性

objective-c - 在非主线程中运行 Cocoa GUI

macros - 宏观规则!宏采用字符串文字 "...",扩展为 "..."和 b"..."