Objective-C 中的单例

作者: 张嘉夫 | 来源:发表于2017-05-10 16:17 被阅读428次

iOS 开发中我最常用的设计模式就是单例模式 。用于在代码间共享数据,极为有效,不需要手动传递数据。Cocoa Design Patterns 这本书写的非常好,里面有很多有关单例模式和其它模式的内容。


后端

单例类是需要重点理解的,它们展示出了一种非常实用的设计模式。整个 iOS SDK 都使用了这个设计模式,例如 UIApplication 有一个方法叫做 sharedApplication,可以在任意地方调用,会返回一个与当前运行应用相关的 UIApplication 实例。


如何实现

在 Objective-C 中,可以使用如下代码实现一个单例类:

MyManager.h

#import <foundation/Foundation.h>

@interface MyManager : NSObject {
    NSString *someProperty;
}

@property (nonatomic, retain) NSString *someProperty;

+ (id)sharedManager;

@end

MyManager.m

#import "MyManager.h"

@implementation MyManager

@synthesize someProperty;

#pragma mark Singleton Methods

+ (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;
}

- (void)dealloc {
  // 应该永远不会被调用,放在这里以表清晰。
}

@end

上面的代码定义了一个叫做 sharedManager 的静态变量(但只在此翻译单元(translation unit)中是全局的),然后在 sharedManager 里初始化了一次,并且永远只有这一次初始化。怎么确保它只被创建一次呢?因为使用了 GCD(Grand Central Dispatch)里面的 dispatch_once 方法。线程安全,完全由操作系统负责,所以就不需要再多担心什么了。

但如果你不想用 GCD,sharedManager 可以采用下面的代码:

+ (id)sharedManager {
    static MyManager *sharedMyManager = nil;
    @synchronized(self) {
        if (sharedMyManager == nil)
            sharedMyManager = [[self alloc] init];
    }
    return sharedMyManager;
}

然后就可以在任意位置调用下面这个函数来引用单例了:

MyManager *sharedManager = [MyManager sharedManager];

我在项目中大量使用了这些代码,例如创建一个单例来处理 CoreLocation 或 CoreData 函数。


无 ARC 代码

虽然我并不推荐这样,但如果你没有用 ARC(Automatic Reference Counting)的话,就应该采用下面的代码:

MyManager.h. 无ARC

#import "MyManager.h"

static MyManager *sharedMyManager = nil;

@implementation MyManager

@synthesize someProperty;

#pragma mark Singleton Methods
+ (id)sharedManager {
  @synchronized(self) {
      if(sharedMyManager == nil)
          sharedMyManager = [[super allocWithZone:NULL] init];
  }
  return sharedMyManager;
}
+ (id)allocWithZone:(NSZone *)zone {
  return [[self sharedManager] retain];
}
- (id)copyWithZone:(NSZone *)zone {
  return self;
}
- (id)retain {
  return self;
}
- (unsigned)retainCount {
  return UINT_MAX; //表示此对象无法被释放
}
- (oneway void)release {
  // 永不释放
}
- (id)autorelease {
  return self;
}
- (id)init {
  if (self = [super init]) {
      someProperty = [[NSString alloc] initWithString:@"Default Property Value"];
  }
  return self;
}
- (void)dealloc {
  // 应该永远不会被调用,放在这里以表清晰。
  [someProperty release];
  [super dealloc];
}

@end

相关文章

  • iOS 单例

    Objective-C 单例宏 Swift 单例声明

  • Swift单例模式

    参考:http://swifter.tips/singleton/ OC写法 在 Objective-C 中单例的...

  • 关于dispatch_once的坑及注意点

    说到单例,在Objective-C中我们很容易就能想到用dispatch_once来构建一个单例的对象,然而最近因...

  • swift中的单例正确写法

    往事回忆之ObjC单例Swift是Objective-C的一种自然演变,它用如下的方式实现单例: 在这个现成方案中...

  • iOS 单例的创建

    Objective-C创建单例 Swift创建单例 确保唯一性 复写allocWithZone、copyWithZ...

  • Objective-C 中的单例

    iOS 开发中我最常用的设计模式就是单例模式 。用于在代码间共享数据,极为有效,不需要手动传递数据。Cocoa D...

  • 面试:iOS代码整理

    一、懒加载 Objective-C Swift 二、单例 Objective-C Swift 三、getter和s...

  • Swift、Objective-C 单例模式 (Singleto

    Swift、Objective-C 单例模式 (Singleton)原文地址:http://www.cnblogs...

  • Singleton in Swift

    单例模式是我们常用的一种设计模式,在Swift中如何使用呢? 先回顾下在Objective-c中的使用 Swift...

  • 单例模式的书写

    ARC OC 中的单例 根据OC单例 改写成 Swift 中的单例 OC调用swift,需要#import "单例...

网友评论

    本文标题:Objective-C 中的单例

    本文链接:https://www.haomeiwen.com/subject/nhjgtxtx.html