許多從 Android 轉戰 iOS 開發的工程師,習慣在 Java 中使用全域變數來跨方法共享資料。但在 Objective-C 中並沒有所謂「全域變數」這個概念,若直接宣告 static 或 extern 往往會導致編譯錯誤或執行時期崩潰。本文將透過一個實際案例,示範如何以單例模式優雅地解決跨方法資料共享問題。
在加速度計委派方法中計算新座標 newX、newY,並需在按鈕點擊事件 clicked: 中取用這兩個值進行碰撞檢測:
-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
int newX = (int)(Button.center.x + valueX);
int newY = (int)(Button.center.y + valueY);
}
-(IBAction)clicked:(id)sender {
// 這裡需要用到 newX、newY
if (newX == randX || newY == randY) { ... }
}
.h 檔宣告 extern int newX; → 連結錯誤.m 檔宣告 static int newX; → 作用域僅限該檔案,無法跨方法存取建立專用的資料容器類別 GlobalVariables,採用線程安全的單例寫法:
@interface GlobalVariables : NSObject
@property (assign, nonatomic) int newX;
@property (assign, nonatomic) int newY;
+ (instancetype)sharedInstance;
@end
@implementation GlobalVariables
+ (instancetype)sharedInstance {
static GlobalVariables *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[GlobalVariables alloc] init];
});
return instance;
}
@end
// 寫入
[GlobalVariables sharedInstance].newX = newX;
[GlobalVariables sharedInstance].newY = newY;
// 讀取
int x = [GlobalVariables sharedInstance].newX;
int y = [GlobalVariables sharedInstance].newY;
dispatch_once 保證單例唯一性下次需要跨類別、跨方法共享資料時,請直接建立單例資料模型,切勿嘗試模擬「全域變數」。