简体   繁体   English

iOS 5+中的Objective-C单例模式

[英]Objective-C singleton pattern in iOS 5+

I've been reading a lot of threads and blog articles about how to implement a singleton in objective-c, several of them maybe being a bit deprecated (year 2010 or earlier), and it seems like people have different opinions regarding this issue... Does Apple have documentation about implementing a singleton? 我一直在阅读很多关于如何在objective-c中实现单例的线程和博客文章,其中一些可能有点被弃用(2010年或更早),似乎人们对此问题有不同的看法。 .. Apple是否有关于实施单例的文档? I couldn't find it. 我找不到它。 If so, could somebody tell me where? 如果是这样,有人可以告诉我在哪里?

I need a singleton for a class that has some both public and private variables. 我需要一个包含公共和私有变量的类的单例。 Currently, this is the implementation I have for such class: 目前,这是我对此类的实现:

@interface MySingleton ()
   @property (strong, nonatomic) NSString *state;
@end

@implementation MySingleton

@synthesize state = _state;
@synthesize count = _count;

static MySingleton *sharedObject = nil;

+ (MySingleton *)sharedInstance
{
   static dispatch_once_t _singletonPredicate;

   dispatch_once(&_singletonPredicate, ^{
      sharedObject = [[super allocWithZone:nil] init];
   });

   return sharedObject;
}

+ (id)allocWithZone:(NSZone *)zone 
{
   return [self sharedInstance];
}

Should be this the recommended way? 这应该是推荐的方式吗? And how should I initialize the instance variables, public and private? 我应该如何初始化实例变量public和private?

Another issue I'd like to make clear about singleton is: will this generate a memory leak? 我想说明单例的另一个问题是:这会产生内存泄漏吗? Is the use of singletons actually recommended in iOS? 在iOS中实际推荐使用单身人士吗?

Thanks 谢谢

The above is correct, along with @miho's comment about includng the static object inside of the sharedInstance method. 以上是正确的,以及@miho关于包含sharedInstance方法内部静态对象的注释。 But there is no reason to override +allocWithZone: . 但是没有理由重写+allocWithZone: . Singletons in ObjC are generally "shared," not forced. ObjC中的单身人士通常是“共享的”,而不是强迫的。 You're free to create other instances of a "singleton." 您可以自由创建“单身”的其他实例。 If it's illegal to create other instances, then you should make init perform an NSAssert rather than fooling the caller in +allocWithZone: . 如果创建其他实例是非法的,那么你应该让init执行NSAssert而不是在+allocWithZone:欺骗调用者+allocWithZone: If your singleton is mutable (and most are), you absolutely should not override +allocWithZone: this way. 如果你的单例是可变的(大多数是),你绝对不应该覆盖+allocWithZone:这样。

Another issue I'd like to make clear about singleton is: will this generate a memory leak? 我想说明单例的另一个问题是:这会产生内存泄漏吗?

No. This object will never be released, but it will always be accessible. 不会。此对象永远不会发布,但始终可以访问。 That is not a leak. 那不是泄密。

Is the use of singletons actually recommended in iOS? 在iOS中实际推荐使用单身人士吗?

Yes, and it is a very common pattern, used all over the Cocoa frameworks. 是的,这是一个非常常见的模式,在Cocoa框架中使用。 That said, there are various other patterns that have started to recently become somewhat popular among developers. 也就是说,最近开始有各种其他模式在开发人员中开始流行。 Dependency Injection is getting some interest, though I don't see it in practice very often. 依赖注入引起了一些兴趣,虽然我不经常在实践中看到它。 Reducing your reliance on singletons can improve testability, and I have been experimenting recently with how to eliminate some of them in my code with some success. 减少对单例的依赖可以提高可测试性,最近我一直在尝试如何在代码中消除其中的一些并取得一些成功。 But they have a long, proud history in Cocoa, and I do not consider them a problem. 但他们在可可有着悠久而自豪的历史,我不认为这是一个问题。

EDIT: you have one actual bug in your code. 编辑:你的代码中有一个实际的错误。 You should be calling [[self alloc] init] , not [[super alloc] init] . 你应该调用[[self alloc] init] ,而不是[[super alloc] init] There's no reason to ever call +allocWithZone: , just use +alloc . 没有理由调用+allocWithZone:只需使用+alloc (The time when ...WithZone: methods were useful has long passed.) (时间...WithZone:方法很有用已经过去了。)

In Xcode, under 'Search Documentation' enter Creating a Singleton Instance . 在Xcode中,在“搜索文档”下,输入“ 创建单例实例” There are lots of results (but the link above, at the bottom of the page, has example code). 有很多结果(但上面的链接,在页面底部,有示例代码)。

Yes, this is the recommended way. 是的,这是推荐的方式。 There is only one small difference of how I use it: I define the sharedObject as static variable inside the + (MySingleton *)sharedInstance method, because it shouldn't be possible to access the variable from anywhere else then from the getter method. 我如何使用它只有一个小的区别:我在+ (MySingleton *)sharedInstance方法中将sharedObject定义为静态变量,因为它不可能从其他任何地方然后从getter方法访问变量。

And no, you won't create a memory leak. 不,你不会造成内存泄漏。 When your app is terminated all reserved memory used by your app will be released anyway and there is no other situation where a static shared instance should get released. 当您的应用程序终止时,您的应用程序使用的所有保留内存都将被释放,并且没有其他情况会释放静态共享实例。 In pre-ARC area it even was common to override the release method do prevent accidentally releasing of the object. 在ARC之前的区域,甚至通常会覆盖release方法,以防止意外释放物体。

A bit of warning using gcd for singletons: 使用gcd对单身人士的一点警告:

dispatch_once(&_singletonPredicate, ^{
      sharedObject = [[super allocWithZone:nil] init];
   });

if the init method for some reason addresses the singleton object directly or indirectly, there will be a deadlock. 如果init方法由于某种原因直接或间接地处理单例对象,则会出现死锁。 For this reason I believe that the more appropriate way to write a singleton is through the 出于这个原因,我认为写一个单例的更合适的方法是通过

+ (void) initialize

method 方法

I am still using the singleton header thingy from CocoaWithLove - may be a bit dated but still works like a charm. 我仍在使用来自CocoaWithLove的单身标题 - 可能有点过时但仍然像魅力一样。 It basically does the same as described here referring to Apples documentation and I would assume at least Apple's documentation ( bottom of this page ) is still valid. 它基本上与此处描述的苹果文档相同,我认为至少Apple的文档( 本页底部 )仍然有效。 There are people assuming it will stay valid indefinitely sine it is the official solution Apple suggested. 有人假设它将无限期保持有效,因为它是Apple建议的官方解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM