7

我是编写单例的新手,我必须为当前的 iOS 项目使用一个。要求之一是它可以被杀死。我知道这违背了单例的设计,但这是应该/可以做的事情吗?

4

7 回答 7

8

当然可以,但是如果您正在寻找一个可以创建,然后在不需要时释放的对象……这听起来像是一个常规对象。:)


通常单例控制自己的生命周期。你会在这里得到片面的讨论,除非你更多地说明这两个要求(一个,你使用一个单例,两个,它可以随意释放),以及为什么它们都对你的情况有意义。

这可能是因为单例包装了一些其他固有的独特资源(如文件资源或网络连接)。如果这是真的,那么通常单例是该资源的“管理者”,您将通过单例的接口公开对该资源的控制。

或者这可能是因为单例对象持有大量内存(某种缓冲区),并且您希望确保在必要时对其进行刷新。如果是这种情况,那么您可以根据需要对其创建和释放内存的每个方法更聪明,或者您可以让单例侦听低内存系统通知并适当地表现。

从本质上讲,我很难构建一个案例,让单例对象本身被释放是真正有意义的。单个基本对象只占用内存中的少量字节,并且闲逛不会伤害任何人。

于 2012-08-14T02:11:55.557 回答
6

几乎我写过的每一个单例(除了完全以 UI 为中心的控制器)最终都被重构为不是单例。每一个。单身的。一。

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

而且,通常,我的应用程序中可能只有一个所述类的实例。这个实例就像一个单例,事实上,我什至可以创建一种方便的方法来获取它,可能是通过应用程序的委托或通过类方法(sharedInstance有时甚至可能被命名)。

所述类包括通常分为两部分的拆解代码;保持当前状态以便稍后恢复的代码和释放实例相关资源的代码。

像单身一样方便。准备好在需要时进行多次实例化。

于 2012-08-14T07:09:18.187 回答
6

我知道这违背了单例的设计

它也违背了 Objective-C 中通常的内存管理模式。通常,一个对象可以保留另一个对象以防止它被销毁,并释放它以允许该对象被销毁。然而,明确地销毁一个对象并不是其他对象可以做的事情。

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

您可能可以通过覆盖-retain甚至 swizzling来解决这个问题-release,但这似乎很复杂,要解决一个原本不应该存在的问题。

一种可能的替代方法是重置您的共享对象,而不是尝试销毁它。如果需要,您可以将其所有属性设置为某个已知(可能无效)的状态,然后使用类方法重新初始化共享对象。请注意所有这些对可能使用共享对象的任何对象的影响。

于 2012-08-14T02:45:06.643 回答
3

好没问题。你提供了一个新的类方法:[MyClass killSingleton]; 该方法释放单例并将其内部引用设置为 nil。下次有人问 [MyClass sharedSingleton] 时,您将按照之前创建它的相同步骤进行操作。

编辑:实际上,在过去,这样的例程可能会覆盖release选择器,并且拒绝消失。因此,正如下面的第一条评论所述,这是一个具有静态作用域的对象——它通过一个静态变量保持活动状态,保持对象的保留计数为 1。但是,通过添加一个新的类方法来消除该 ivar(在 ARC 下),从而释放它,可以达到预期的结果。对静态对象的实例化和释放的控制完全通过类方法完成,因此易于维护和调试。

于 2012-08-14T02:12:28.930 回答
1

这与 Singleton 的概念背道而驰,但是对于基于 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
于 2014-01-10T04:21:08.840 回答
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
于 2014-08-27T09:42:25.957 回答
0

我需要清除单例,所以我最终做了以下事情:

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

希望能帮助到你。

于 2016-03-17T15:00:33.057 回答