我知道Singleton模式已经讨论过了很多。但是因为我还没有完全理解Objective-C中的内存管理机制,所以当我将Singleton实现与多线程结合起来时,我遇到了一个很大的错误,花了我一整天来解决它。
我有一个单身对象,我们称之为ObjectX
。我在ObjectX
内声明了一个将分离新线程的对象,当我调用
objectWillSpawnNewThread
[[ObjectX sharedInstance].objectWillSpawnNewThread startNewThread];
新线程无法正确执行,最后我发现我不应该在singleton类中声明对象objectWillSpawnNewThread
。
以下是我的问题:
我搜索了Objective-C语言[ObjC.pdf
]和Objective-C memory management
文档,也许我错过了一些内容,但目前我找不到任何有用的信息。
答案 0 :(得分:1)
了解内存管理规则。它们很简单,一周之内你就会有时间投资。
忘记单身人士。更确切地说,忘记代码强制执行的单身人士。它们不必要地复杂化,99%的时间都是糟糕的设计。
阅读MiškoHevery的Singletons are Pathological Liars,仔细阅读,阅读所有相关博客文章并思考一下。大多数情况下,没有真正需要一个类来强制执行单个实例。通常,您可以通过创建某种类型的Factory类来解决问题,该类将为您创建大多数实例并将它们连接在一起:
@interface Factory {
id classYouWantJustOneInstanceOf;
}
- (id) wireMainController;
@implementation Factory
- (id) init {
[super init];
// No “sharedFoo” stuff necessary. Foo is a plain
// class without singleton boilerplate, easily testable.
classYouWantJustOneInstanceOf = [[Foo alloc] init];
return self;
}
- (id) wireMainController {
id controller = [[SomeClass alloc] init];
// Dependencies set explicitly, good.
[controller setFoo:classYouWantJustOneInstanceOf];
return [controller autorelease];
}
@implementation UIApplicationDelegate
- (void) applicationDidFinishLauching: (UIApplication) app {
// Now all your “singletons” will get created,
// no funny static stuff.
factory = [[Factory alloc] init];
controller = [[factory wireMainController] retain];
[window addSubview:controller.view];
// up and running
}
- (void) dealloc {
[controller release];
// Now all your “singletons” will get released.
[factory release];
[super dealloc];
}
我知道与“简单”[Foo sharedFoo]
相比,这感觉有些不安,但是值得,相信我。
此解决方案的优点,如果不明显:
班级中没有单独的样板文件。没有静态共享实例,没有线程同步,没有。
明确的依赖关系管理。如果A类需要B的实例来完成它的工作,你可以从公共setter或A的构造函数参数中看到它。实现文件中没有惊人的依赖。如果您需要以不同的方式连接A,比如说出于测试目的,当依赖关系是显式的时(与调用[B sharedB]
相反),它会更容易。
清除对象生命周期。没有静态变量,没有静态初始化,也没有延迟初始化,除非你真的需要它。您知道何时创建对象并且您可以释放您创建的所有内容。
请注意,这是一个简化的案例,因此应用程序委托和Factory之间的划分看起来有点迂腐,但在实际情况下它很有意义(参见Principle of single responsibility)。
答案 1 :(得分:0)
除非你发布一些代码,否则很难说你做错了什么,但单身对象没有任何魔力。作为静态对象,没有任何东西。
问题1:
所有Objective-C对象都是从堆中分配的。您可以从任何范围声明指向它们的指针,但是在代码中的某个地方,直接或间接地,必须向对象的类发送alloc消息,并将结果指针初始化并分配给指针。必须在对象的init方法中初始化对象的实例变量。因此,实现单例的一种方法如下:
// Header
@interface ObjectX : NSObject
{
SpawnObject* objectWillSpawnNewThread;
}
+(ObjectX*) sharedInstance;
// Implementation
@implementation ObjectX
-(id) init
{
self = [super init];
if (self != nil)
{
objectWillSpawnNewThread = [[SpawnObject alloc] init];
}
return self;
}
+(ObjectX*) sharedInstance
{
static ObjectX* sharedInstance;
@synchronized([ObjectX class])
{
if (sharedInstance == nil)
{
sharedInstance = [[ObjectX alloc] init];
}
}
return sharedInstance;
}
@end
问题2:
除非您发布代码和错误消息,否则无法告诉您答案。但是,一个常见问题是忘记在新线程中设置自动释放池。