我正在开发一个Cocoa(Touch)应用程序,并且我必须在不同的视图和控制器之间保留某些数据(如自己的设备信息和位置列表)。
我想过将它作为实例变量存储在我的App Delegate中,但是对代理进行寻址是非常麻烦的(每次我想访问位置数组时都没有快乐键入[[[UIApplication sharedApplication] delegate] locations]
,而且很多地方),所以我想为代理引入某种别名(la NSApp),但除了NSApp之外,我还没有在其他Cocoa应用程序中经常看到这种情况。
我还想进一步为我的单例类引入别名,所以不是[State sharedState]
,而是为什么不将类重命名为_State
并将它的一个实例称为State?< / p>
答案 0 :(得分:1)
我可能会写一个类似于LocationManager的类,它给出了一个带有[LocationManager sharedManager]或类似功能的单例。通过委托调用会破坏封装(并且您通过3个对象调用来实现)。即使是NSApp风格的#define也无法解决这个问题。
答案 1 :(得分:1)
使用方法调用来获取单例的主要目的是可以懒惰地准备单例。例如:
static State sharedStateInstance;
@implementation State
+ (id)sharedState {
if (!sharedStateInstance)
sharedStateInstance = /* Allocate instance */;
return sharedStateInstance;
}
@end
所以这意味着如果没有代码调用+sharedState
,则不会花费任何资源来创建它。
此外,如果将来出现其他需求,可以在一个地方改进此代码,例如确保每个线程有一个实例,或者所有线程的共享实例(然后需要在初始化时锁定代码)。 / p>
答案 2 :(得分:1)
Cocoa鼓励使用[Foo sharedFoo]
而不是全局Foo对象有几个原因。
[Foo sharedFoo]可以在第一次使用时自动实例化。
用大写字母命名实例非常令人困惑,因为它看起来像一个类,鼓励错误。命名的一致性是良好Objective-C的核心。编译器不能保护您免受各种各样的错误,因为ObjC是高度动态的。良好的命名和一致性自律是导致无错Cocoa的原因。
平行度:
Foo *foo = [Foo sharedFoo];
Foo *foo = [[[Foo alloc] init] autorelease];
Foo *foo = [Bar fooAtIndex:0];
所有这三个在同一个程序中可能是合法的。仅仅因为存在单例实例并不意味着也没有其他实例。 NSNotificationCenter就是一个很好的例子。它是一个单例,但您可以创建其他实例(并且有理由这样做)。
可以全局修改全局变量。 sharedInstance
不可以。例如,如果State
是全局变量(而不是类),则State=nil
在程序中的任何位置都是合法的。这破坏了封装,并且是编译器无法捕获的state=nil
的简单错字。如果State
是一个类,那么编译器可以捕获这个简单的错误。
Cocoa命名的许多规则是为了鼓励高度可读的代码,并在高度动态和松散类型的环境中最小化错误。就像Perl的use strict
一样,在放弃我们拥有的小安全网之前,我们应该非常小心。
答案 3 :(得分:0)
#define FOO [[[UIApplication sharedApplication] delegate] locations]