首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Objective-C 單例模式完整實作指南(含 GCD 與非 ARC 版本)

     編輯:關於C語言

單例模式在 iOS 開發中的地位

單例模式是 iOS 開發中最常見的設計模式之一。系統框架大量採用:UIApplication.sharedApplication、NSFileManager.defaultManager、NSNotificationCenter.defaultCenter 等皆為單例。它讓各模組共享同一實例,避免手動傳遞參考,同時確保資源唯一性。

現代標準寫法(GCD + ARC)

利用 dispatch_once 保證線程安全且僅初始化一次,程式碼簡潔且為 Apple 官方推薦。

ShareData.h

#import <Foundation/Foundation.h>

@interface ShareData : NSObject
@property (nonatomic, strong) NSString *string;
+ (instancetype)sharedData;
@end

ShareData.m

#import "ShareData.h"

@implementation ShareData

+ (instancetype)sharedData {
    static ShareData *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        _string = @"123"; // ARC 下無需 autorelease
    }
    return self;
}

@end

使用方式

ShareData *data = [ShareData sharedData];
NSLog(@"%@", data.string); // 123
data.string = @"456";
// 其他處取得同一實例
ShareData *data2 = [ShareData sharedData];
NSLog(@"%@", data2.string); // 456

非 ARC 環境下的完整實作

早期專案或需相容舊代碼時,必須手動管理記憶體並覆寫 retain/release/autorelease/allocWithZone:/copyWithZone: 等方法,確保單例不可被釋放或複製。

#import "ShareData.h"

static ShareData *_sharedInstance = nil;

@implementation ShareData
@synthesize string = _string;

+ (id)sharedData {
    @synchronized(self) {
        if (_sharedInstance == nil) {
            _sharedInstance = [[super allocWithZone:NULL] init];
        }
    }
    return _sharedInstance;
}

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

- (id)copyWithZone:(NSZone *)zone { return self; }
- (id)retain { return self; }
- (NSUInteger)retainCount { return NSUIntegerMax; }
- (void)release { /* never release */ }
- (id)autorelease { return self; }

- (id)init {
    self = [super init];
    if (self) { _string = [[NSString alloc] initWithString:@"123"]; }
    return self;
}

- (void)dealloc {
    [_string release];
    [super dealloc];
}
@end

關鍵點總結

場景推薦做法核心機制
現代 ARC 專案GCD dispatch_once系統保證線程安全、僅執行一次
非 ARC 舊專案@synchronized + 覆寫記憶體管理方法手動鎖定、禁止釋放/複製
Swift 專案static let shared = MyClass()語言層級保證 lazy + thread-safe

常見錯誤與避坑指南

  • 忘記 static 修飾靜態變數:導致每次呼叫都重新分配。
  • 在 dispatch_once 區塊外初始化:失去線程安全保證。
  • 非 ARC 下漏寫 allocWithZone::[[MyClass alloc] init] 會繞過單例邏輯。
  • 單例持有大量狀態:造成隱性耦合,單元測試困難,建議改用依賴注入。

延伸閱讀

  • Apple 官方文件:Creating a Singleton Instance
  • Mike Ash 深度解析:Singleton Pattern in Objective-C
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved