• <转>Singletons in Objective-C


    转自:这里

    Singletons in Objective-C

    One of my most used design patterns when developing for iOS is the singleton pattern. It’s an extremely powerful way to share data between different parts of code without having to pass the data around manually. More about the singleton pattern and other patterns can be found in this excellent book:

    Background

    Singleton classes are an important concept to understand because they exhibit an extremely useful design pattern. This idea is used throughout the iPhone SDK, for example, UIApplication has a method called sharedApplication which when called from anywhere will return the UIApplication instance which relates to the currently running application.

    How to implement

    You can implement a singleton class in Objective-C using the following code:

    MyManager.h

    1 #import <foundation/Foundation.h>
    2 @interface MyManager : NSObject {
    3     NSString *someProperty;
    4 }
    5 @property (nonatomic, retain) NSString *someProperty;
    6 + (id)sharedManager;
    7 @end
    View Code

    MyManager.m

      
     1 #import "MyManager.h"
     2 @implementation MyManager
     3 @synthesize someProperty;
     4 #pragma mark Singleton Methods
     5 + (id)sharedManager {
     6     static MyManager *sharedMyManager = nil;
     7     static dispatch_once_t onceToken;
     8     dispatch_once(&onceToken, ^{
     9         sharedMyManager = [[self alloc] init];
    10     });
    11     return sharedMyManager;
    12 }
    13 - (id)init {
    14   if (self = [super init]) {
    15       someProperty = [[NSString alloc] initWithString:@"Default Property Value"];
    16   }
    17   return self;
    18 }
    19 - (void)dealloc {
    20   // Should never be called, but just here for clarity really.
    21 }
    22 @end
    View Code

    What this does is it defines a static variable (but only global to this translation unit)) called sharedMyManager which is then initialised once and only once in sharedManager. The way we ensure that it’s only created once is by using the dispatch_once method from Grand Central Dispatch (GCD). This is thread safe and handled entirely by the OS for you so that you don’t have to worry about it at all.

    However, if you would rather not use GCD then you should use the following code for sharedManager:

    Non-GCD based code

    1 + (id)sharedManager {
    2     static MyManager *sharedMyManager = nil;
    3     @synchronized(self) {
    4         if (sharedMyManager == nil)
    5             sharedMyManager = [[self alloc] init];
    6     }
    7     return sharedMyManager;
    8 }
    View Code
     

    Then you can reference the singleton from anywhere by calling the following function:

    MyManager *sharedManager = [MyManager sharedManager];
    

    I’ve used this extensively throughout my code for things such as creating a singleton to handle CoreLocation or CoreData functions.

    Non-ARC code

    Not that I recommend it, but if you are not using Automatic Reference Counting (ARC), then you should use the following code:

    MyManager.h non-ARC

     1 #import "MyManager.h"
     2 static MyManager *sharedMyManager = nil;
     3 @implementation MyManager
     4 @synthesize someProperty;
     5 #pragma mark Singleton Methods
     6 + (id)sharedManager {
     7   @synchronized(self) {
     8       if(sharedMyManager == nil)
     9           sharedMyManager = [[super allocWithZone:NULL] init];
    10   }
    11   return sharedMyManager;
    12 }
    13 + (id)allocWithZone:(NSZone *)zone {
    14   return [[self sharedManager] retain];
    15 }
    16 - (id)copyWithZone:(NSZone *)zone {
    17   return self;
    18 }
    19 - (id)retain {
    20   return self;
    21 }
    22 - (unsigned)retainCount {
    23   return UINT_MAX; //denotes an object that cannot be released
    24 }
    25 - (oneway void)release {
    26   // never release
    27 }
    28 - (id)autorelease {
    29   return self;
    30 }
    31 - (id)init {
    32   if (self = [super init]) {
    33       someProperty = [[NSString alloc] initWithString:@"Default Property Value"];
    34   }
    35   return self;
    36 }
    37 - (void)dealloc {
    38   // Should never be called, but just here for clarity really.
    39   [someProperty release];
    40   [super dealloc];
    41 }
    42 @end
    View Code

    Updates

    • EDIT: Added property to MyManager.
    • EDIT: Updated as per Apple’s guidelines to pass static analysis.
    • EDIT: Updated to support ARC.
    • EDIT: Switched to use the more common GCD approach.

      

     在NonGCD及NonARC的代码中,使用了synchronized关键字,用于多线程的加锁同步。关于多线程的同步,可以参考官方文档:Threading Programming Guide

    这里有部分的中文翻译:这里

    在创建单例时建议使用GCD的方式,代码简洁,由于被dispath_once修饰的代码只执行一次,因而速度更快。

  • 相关阅读:
    discuz Ucenter第三方双向同步登录
    python: 输出 1~100 之间不能被 7 整除的数,每行输出 10 个数字,要求应用字符串格式化方法美化输出格式。
    用python语言来判断一个数是否是水仙花数?
    java如何调用webservice接口
    ASP.NET 全局变量和页面间传值方法
    从客户端中检测到有潜在危险的 Request.Form 值] 处理办法
    第一次作业要点及重要属性
    Servlet生命周期
    cookie与session的比较
    零基础学习HTML5
  • 原文地址:https://www.cnblogs.com/ioooooos/p/3539682.html
Copyright © 2020-2023  润新知