2012-08-14 32 views
5

我是新手写单身人士,我必须使用一个当前的iOS项目。其中一个要求是它可以被杀死。我知道这与单身人士的设计背道而驰,但这是应该/可以完成的事情吗?完全释放一个Objective-C的单身人士

+0

根据定义,单再也不能重新分配,因此,重新分配的概念没有任何意义。撕下来终止?当然。但无论如何,你都不能依赖这种发生。 – bbum 2012-08-14 02:18:49

+0

@bbum这取决于定义。对我来说,这个明确的定义来自标志性的GoF书:“确保一个班只有一个实例”。这并不排除破坏和重建。 – 2012-08-14 02:35:46

+1

然后按照Cocoa和iOS开发中的定义。 – bbum 2012-08-14 04:18:53

回答

6

当然,它可以可以完成,但如果你正在寻找一个对象,可以创建,然后释放时,不需要......这听起来像一个普通的对象。 :)


通常单身人士控制自己的生命周期。你会在这里进行单方面的讨论,除非你更多地谈论这两个要求(一个是你用一个单身人士,另外两个是可以随意发布的),以及他们为什么对你的情况有意义。

这可能是因为singleton包装了一些固有唯一的其他资源(如文件资源或网络连接)。如果这是真的,那么通常单身人士是该资源的“管理者”,并且你将通过单身人士的界面暴露该资源的控制权。

或者它可能是因为单例对象持有大量内存(某种缓冲区),并且您希望确保按需刷新。如果是这样的话,那么你可以根据需要更聪明地创建和释放内存,或者你可以让单例监听低内存系统通知并且适当地运行。

本质上,我很难建立一个案例,它真的有意义的发布单身物件本身。一个基本的对象在内存中只占用少量的字节,并且不会因为闲逛而伤害任何人。

+0

我必须将现有的应用程序转换为静态库,并且必须将所有AppDelegate逻辑转换为Singleton以实现最少的代码重构。 “库应用程序”需要能够通过使其成为窗口的rootview控制器或由其他视图控制器呈现/推送来呈现。在rootviewcontroller情况下,单身人士会忠于设计而永远不会被杀死,另外两种情况我认为是为什么要求能够杀死它。 – MattDice 2012-08-14 02:30:01

+3

@MattDice:明白了,但你最好在此设计。如果库的“AppDelegate”实际上没有状态(属性),那么可以使用一次机械搜索/替换将其所有方法转换为类方法。如果它确实带有状态(并且因此实际上变成了全局变量的容器),那么考虑是否有必要破坏它 - 也许将它留在任何单身人士身边都可以。如果您必须重置状态,请考虑添加某种'-reset'方法,将其属性恢复为默认状态。 – 2012-08-14 02:37:47

+1

@MattDice:请记住,如果您可以在导航堆栈中同时存在多个这样的“库应用程序”,那么如果您希望为它们独立保存状态,则甚至不能使用单例;在这种情况下,你真的需要重构。 – 2012-08-14 02:39:14

3

当然没问题。你提供了一个新的类方法:[MyClass killSingleton];该方法释放单例并将其内部引用设置为nil。下一次有人询问[MyClass sharedSingleton]时,你会经历与之前相同的步骤来创建它。

编辑:实际上,在过去,这样的例程可能会覆盖release选择器,并拒绝离开。正如下面的第一条评论所指出的那样,这是一个静态范围的对象 - 它通过一个静态变量保持活动状态,在对象上保留1。然而,通过添加新的类方法来淘汰伊娃(在ARC下),从而释放它,达到期望的结果。实例化和释放静态对象的控制完全是通过类方法完成的,因此易于维护和调试。

+1

这不再是一个单例,那么><仅仅是一个具有静态作用域的常规对象。 – borrrden 2012-08-14 02:26:06

+1

你的评论比答案更适合这个问题。我只是回答问题,而不是判断人们使用技术术语。我敢肯定,如果我们在酒吧讨论这个问题,并且手头有品脱,我们都会采取不同的解决方案来解决问题。 – 2012-08-14 10:44:37

5

我知道这违背了单

这也违背在Objective-C通常的内存管理模式的设计。通常情况下,对象会保留另一个对象以防止它被销毁,并释放它以允许对象被销毁。但是,显式销毁一个对象并不是其他对象可以做的事情。

考虑如果对象A获取单例类S的共享实例S1会发生什么。如果A保留S1,即使某些类方法释放S并设置指向共享实例的全局变量,S1也将继续存在到零。当班级以后创建一个新的共享实例S2时,会有两个S的实例,即S1和S2。这违反了首先定义单例的属性。

您可以通过覆盖-retain或者更改-release来解决这个问题,但这似乎是解决一个本来不应该存在的问题的复杂问题。

可能的替代方法是重置您的共享对象,而不是试图摧毁它。如果你愿意,你可以将它的所有属性设置为已知(可能无效)的状态,然后有一个类方法重新初始化共享对象。只需注意所有可能使用共享对象的对象的效果。

5

几乎每一个我曾经写过单(除完全UI中心控制器)最终被重构到不是单身。每一个。单。一。

因此,我停笔单身。我编写了维护实例的类,就像任何普通的类一样,并且与其他实例隔离开来。如果他们通知很重,他们总是通过self作为通知对象。他们有代表。他们保持内部状态。它们避免了真正的全球状态之外的全局变量。

而且,通常情况下,有可能是只有一个在我的应用程序(S)表示类的实例。这个实例就像一个单例,事实上,我甚至可能通过应用程序的委托或通过类方法(有时甚至可能将其命名为sharedInstance)创建一个方便的方法来获取它。

所述类包括拆除代码典型地在两片划分;以后继续保持当前状态以恢复的代码以及释放实例关联资源的代码。

像单身人士一样方便。准备在需要时实例化。

1

这是对辛格尔顿的概念,但它可以实现一个ARC基于项目

//ARC 
@interface Singleton : NSObject 

+ (Singleton *)sharedInstance; 
+ (void)selfDestruct; 

@end 

@implementation Singleton 

static Singleton *sharedInstance = nil; 

+ (Singleton *)sharedInstance { 
    if (sharedInstance == nil) { 
     sharedInstance = [[Singleton alloc] init]; 
    } 
    return sharedInstance; 
} 

+ (void) selfDestruct { 
    sharedInstance = nil; 
} 

@end 
+1

这不起作用。如果在将它设置为nil后检查了sharedInstance,它将存在于内存中。另外,如果sharedManager保留在任何其他对象中,这不会提供任何帮助。 – 2014-03-08 00:51:59

0
//This can be implemented using bool variable. If bool no create new instance. 

@interface Singleton : NSObject 

+ (Singleton *)sharedInstance; 

@end 

@implementation Singleton 

static Singleton *sharedInstance = nil; 

+ (Singleton *)sharedInstance { 

     if (!keepInstance) { 
       sharedInstance = [[Singleton alloc] init]; 
       keepInstance = YES; 
     } 
     return sharedInstance; 
} 

@end 
0

我需要清除掉单通过以下方式,所以我最终做了以下内容:

- (void)deleteSingleton{ 
@synchronized(self) { 
    if (sharedConfigSingletone != nil) { 
     sharedConfigSingletone = nil; 
    } 
} 
} 

希望它能帮助。