【问题标题】:How to create singleton class in objective C如何在目标 C 中创建单例类
【发布时间】:2011-03-21 17:07:33
【问题描述】:

如何在 Objective C 中创建单例类?

【问题讨论】:

标签: iphone objective-c singleton


【解决方案1】:

好的 appDev,您可能会在网络上找到很多不同的技术来执行此操作。但是,对于 iOS 应用开发,我认为最方便的方法是执行以下操作:

  • 编写获取单例对象的方法。 (建议:为此使用dispatch_once 线程和 GCD)。

  • 将您的方法包装在一个宏中并将其添加到您的$Project$-Prefix.pch 文件中。

  • 当你需要一个类的单例对象时调用单行宏。

例子:

CommonMacros.h

#define SINGLETON_FOR_CLASS(classname)
+ (id) shared##classname {
    static dispatch_once_t pred = 0;
    static id _sharedObject = nil;
    dispatch_once(&pred, ^{
        _sharedObject = [[self alloc] init];
    });
    return _sharedObject;
}

YourProject-Prefix.pch:

...
#import "CommonMacros.h"
...

YourSingletonClass.m:

...
SINGLETON_FOR_CLASS(YourSingletonClass)
...
【解决方案2】:

查看此链接以获取原始来源 - http://getsetgames.com/2009/08/30/the-objective-c-singleton/

@implementation MySingleton
static MySingleton *_sharedMySingleton = nil;

+(MySingleton *)sharedMySingleton {
    @synchronized([MySingleton class]) {
        if (!_sharedMySingleton)
          _sharedMySingleton = [[self alloc] init];
        return _sharedMySingleton;
    }
    return nil;
}

【讨论】:

  • 这很好,但缺少分配:_sharedDataModel = [[self alloc] init];
  • @ChuckH:自己不代表_sharedMySingleton吗?
  • @Chandu:在上面的示例中,self 不是指 MySingleton 类的实例,它指的是 MySingleton 类对象。如果按原样编译,编译器将给出警告,指出 [[self alloc] init] 表达式的结果未使用。但是,上面的示例仅有效,因为指向原始源的链接还包含一个 alloc 类方法,该方法最终完成了所需的分配。我觉得去掉alloc类方法,直接用单例实例的alloc/init的结果做静态变量赋值会容易很多。
  • 网址已过时
【解决方案3】:

我确实认为这是我们真正实现单例行为的方式:

@interface SampleSingletonClass : NSObject

+ sharedSampleSingletonClass;

@end


@implementation SampleSingletonClass
static SampleSingletonClass *singletonObject = nil;

+ (id) sharedSampleSingletonClass
{
    if (! singletonObject) {

        singletonObject = [[SampleSingletonClass alloc] init];
    }
    return singletonObject;
}

- (id)init
{
    if (! singletonObject) {

        singletonObject = [super init];
    // Uncomment the following line to see how many times is the init method of the class is called
    // NSLog(@"%s", __PRETTY_FUNCTION__);
    }
    return singletonObject;
}

@end

这里即使调用了 init 方法而不是预期的 + (id) SampleSingletonClass;方法实际对象在应用程序的整个生命周期中只形成一次。

【讨论】:

  • 我一直怀疑如果有人明确调用 init 会怎样。知道如何在 Swift 中做到这一点,一个纯单例。
  • @anoop4real 不允许显式调用 init,请将 init 设为私有。
  • @anoop4real class Class { static let shared = Class() private init() {} }
【解决方案4】:

这是我个人最喜欢的方式:

+ (instancetype)sharedObject {
    static id instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc] init];
    });
    return instance;
}

【讨论】:

  • 如果有人显式调用 init 怎么办?
  • 我认为您对此无能为力,ObjC 并没有真正的“私有”与“公共”的概念。
  • 只需加上 + (instancetype) init __attribute__((unavailable("init() is available")));到 .h 文件。这将使调用 init 的代码无法编译。
【解决方案5】:

你可以在 Objective-C 中实现一个单例类。

+ (id)sharedManager {
    static MyManager *sharedMyManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedMyManager = [[self alloc] init];
    });
    return sharedMyManager;
}

- (id)init {
  if (self = [super init]) {
      someProperty = [[NSString alloc] initWithString:@"Default Property Value"];
  }
  return self;
}

http://www.galloway.me.uk/tutorials/singleton-classes/

【讨论】:

  • 请注意,不鼓励link-only answers,所以答案应该是搜索解决方案的终点(与另一个参考文献的中途停留相比,随着时间的推移往往会变得陈旧)。请考虑在此处添加独立的概要,并保留链接作为参考。
【解决方案6】:

发件人: http://www.galloway.me.uk/tutorials/singleton-classes/

Objective-C 中的单例

在为 iOS 开发时,我最常用的设计模式之一是单例模式。这是一种非常强大的方式,可以在代码的不同部分之间共享数据,而无需手动传递数据。

背景

单例类是一个需要理解的重要概念,因为它们展示了一种非常有用的设计模式。这个想法在整个 iPhone SDK 中都有使用,例如,UIApplication 有一个名为 sharedApplication 的方法,当从任何地方调用该方法时,将返回与当前运行的应用程序相关的 UIApplication 实例。

如何实施

Singletone.h

#import <foundation/Foundation.h>

@interface Singleton : NSObject {
}

 @property (nonatomic, retain) NSString *someProperty;

  + (id)sharedManager;

 @end

Singleton.m

#import "Singleton.h"

@implementation Singleton

@synthesize someProperty;

#pragma mark Singleton Methods

 + (id)sharedManager {
   static Singleton *sharedMyManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
    sharedMyManager = [[self alloc] init];
  });
  return sharedMyManager;
 }

 - (id)init {
  if (self = [super init]) {
     someProperty = [[NSString alloc] initWithString:@"Default Property Value"];
  }
return self;
}

@end

它的作用是定义一个名为 sharedMyManager 的静态变量(但仅限于该翻译单元的全局变量),然后在 sharedManager 中初始化一次且仅一次。我们确保它只创建一次的方法是使用 Grand Central Dispatch (GCD) 中的 dispatch_once 方法。这是线程安全的,完全由操作系统为您处理,因此您完全不必担心。

【讨论】:

  • 先生为什么 Class *classObj = nil; 这意味着指针对象没有指向内存中的任何内容。以及这个静态关键字在这里到底是做什么的,请解释一下。
  • More over "nil 用于表示一个指向 Objective-C 对象的空指针。nil 用于表示一个指向 Objective-C 类的空指针。” 所以sharedMyManager 是 Objective-C 对象或类对象。但我相信 sharedMyManager 是一个指向单例类的指针对象。
【解决方案7】:

试试这个

Singalton 类 .h 文件

#import <Foundation/Foundation.h>

@interface GlobleDirector : NSObject
+(GlobleDirector*)shareManager;
@end

Singalton 类 .m 文件

#import "GlobleDirector.h"

@implementation GlobleDirector


+(GlobleDirector*)shareManager{

static GlobleDirector *sharedInstance=nil;
static dispatch_once_t  oncePredecate;

dispatch_once(&oncePredecate,^{
    sharedInstance=[[GlobleDirector alloc] init];

 });
return sharedInstance;
}



@end

【讨论】:

    【解决方案8】:
        static DBHandler* sDBHandler = nil;
    
    - (id)init
    {
        self = [super init];
        if (self) {
            [self checkAndCreateDatabase];
        }
        return self;
    }
    
    +(id)sharedDBHandler
    {
        @synchronized (self) {
            if (sDBHandler == nil) {
                sDBHandler = [self new];
            }
        }
        return sDBHandler;
    }
    

    【讨论】:

      【解决方案9】:

      我知道访问者应该知道什么是单例,但为了帮助那些他们不知道的人,我提出了一个共享数据的简单小示例。

      该对象用于共享数据类实例或类实例。

      @interface SharedData : NSObject {
          id data;
      }
      - (void)setData:(id)data_;
      - (id)data;
      @end
      
      @implementation SharedData
      //>> singleton
      static SharedData *sharedData=nil;
      + (SharedData*)sharedData {
          @synchronized (self) {
              if (sharedData==nil) sharedData=[[self alloc]init];
          }
          return sharedData;
      }
      //<<
      - (void)setData:(id)data_ {
          data=data_;
      }
      - (id)data {
          return data;
      }
      @end
      

      ... 第一次调用 (+ sharedData) 实例化对象,基于它作为实例引用返回的静态(区域设置共享)变量的引用。下一次调用只返回对静态变量的引用。

      可以使用嵌入式访问器随时设置/获取数据。

      共享对象相对简化,但可以通过引用共享“手动”处理。

      @synchronized 只需要多线程。对于简单的类实例,不需要共享它。

      这里有一个扩展的解释:http://www.galloway.me.uk/tutorials/singleton-classes/

      【讨论】:

        【解决方案10】:
        #import <Foundation/Foundation.h>
        
        @interface singt : NSObject  
        
        + (id)sharedManager;
        
        @end
        
        
        #import "singt.h"
        
        @implementation singt
        
        
        + (id)sharedManager 
        
        {
        
            static singt *sharedMyManager = nil;
             static dispatch_once_t onceToken;
        
            dispatch_once(&onceToken, ^{
                sharedMyManager = [[self alloc] init];
        
        
            });
        
            return sharedMyManager;
        
        }
        

        【讨论】:

        • 您好 Acharya,欢迎来到 SO 并感谢您的回答。此处不鼓励仅使用代码的答案,因为其他人可能难以理解和学习。你认为你可以编辑你的答案来解释为什么这可以解决 OP 的问题吗?非常感谢。
        【解决方案11】:

        这是创建单例类的正确方法

        mySingletonClass.h
        
        @interface mySingletonClass : NSObject
        
         + (mySingletonClass*)sharedInstance;
         @property (nonatomic, assign)BOOL      useToken;
        
        
        
        mySingletonClass.m
        
        @implementation mySingletonClass
        
        static mySingletonClass *_sharedInstance = nil;
        
        
        + (mySingletonClass*)sharedInstance
        {
            static dispatch_once_t onceToken;
            dispatch_once(&onceToken, ^{
                _sharedInstance = [[self alloc] init];
        
            });
        
            return _sharedInstance;
        }
        

        如何访问另一个类中的单例类属性或方法

        另一个类.m

        Bool isTokenValid = [mySingletonClass sharedInstance].useToken;
        

        【讨论】:

          【解决方案12】:

          请尝试以下代码。

          @implementation AppShared
          static AppShared *singletonInstance;
          
          + (AppShared*)Instance{
          if (singletonInstance == nil) {
              singletonInstance = [[super alloc] init];
          }
          return singletonInstance;
          }
          

          【讨论】:

            【解决方案13】:
            + (id)sharedInstance {
                static dispatch_once_t pred = 0;
                __strong static id _sharedObject = nil;
                dispatch_once(&pred, ^{
                    _sharedObject = [[self alloc] init];
                });
                return _sharedObject;
            }
            
            - (id)init {
                self = [super init];
                if (self) {
                }
                return self;
            }
            

            并在 .h 中添加

            + (id)sharedInstance;
            

            PD:你的类应该继承自 NSObject 。

            记住要使用sharedinstance时总是调用它,而不是调用init。

            【讨论】:

              【解决方案14】:

              swift 1.2 或更高版本中,如果类名是例如:singletonVC

              class singletonVC {
              
                  static let sharedMySingleton = singletonVC()
              
                  private init(){ 
                  }
              
              }
              

              实施:

              singletonVC.sharedMySingleton.yourFunctionName
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2012-05-27
                • 1970-01-01
                • 1970-01-01
                • 2018-04-06
                • 1970-01-01
                • 2012-05-28
                • 1970-01-01
                • 2020-04-24
                相关资源
                最近更新 更多