網絡層基類 `BaseNetwork` 派生多個子類(`LoginRequest`、`DataRequest` 等)。每個請求對象持有唯一 URL。需求:任意處調用**類方法** `[LoginRequest cancelAll]` 取消該類所有進行中請求,但類方法無法訪問實例屬性 `url`。
利用 Objective-C 運行時的**關聯對象**機制,將 URL 綁定到**類對象**本身(類也是對象,元類實例)。
// BaseNetwork.h #import@interface BaseNetwork : NSObject @property (copy, nonatomic) NSString *url; + (void)cancelRequest; // 類方法取消請求 @end // BaseNetwork.m #import "BaseNetwork.h" #import static const char *kURLKey = "BaseNetworkURLKey"; @implementation BaseNetwork - (void)setUrl:(NSString *)url { // 綁定到類對象 (self 是實例,[self class] 獲取類對象) objc_setAssociatedObject([self class], kURLKey, url, OBJC_ASSOCIATION_COPY_NONATOMIC); } + (void)cancelRequest { NSString *url = objc_getAssociatedObject([self class], kURLKey); NSLog(@"取消請求 URL: %@", url); // 此處調用網絡庫取消邏輯,如 [AFHTTPSessionManager cancelRequestWithURL:url]; } @end
// LoginRequest.h @interface LoginRequest : BaseNetwork // 繼承 url 屬性與 cancelRequest 類方法 @end // 使用示例 LoginRequest *req = [[LoginRequest alloc] init]; req.url = @"https://api.example.com/login"; // ... 發起請求 ... // 任意處取消(無需持有 req 實例) [LoginRequest cancelRequest]; // 輸出:取消請求 URL: https://api.example.com/login
| API | 作用 | 關鍵參數 |
|---|---|---|
| objc_setAssociatedObject | 綁定關聯 | object(類對象), key, value, policy(內存語義) |
| objc_getAssociatedObject | 獲取關聯 | object, key |
| OBJC_ASSOCIATION_COPY_NONATOMIC | 複製策略 | 非原子、copy 語義,適合 NSString |
C++ 派生類各有獨立靜態成員;OC 靜態變量全派生類共享。用關聯對象綁定到**各自類對象**,實現「每個類一份獨立存儲」。
// 基類
+ (void)setClassConfig:(id)config {
objc_setAssociatedObject(self, @selector(classConfig), config, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
+ (id)classConfig {
return objc_getAssociatedObject(self, @selector(classConfig));
}
// 子類 A、B 各自調用 setClassConfig,互不干擾
`objc_setAssociatedObject` 是 Objective-C 動態性的強大體現,**為類對象添加「實例變量」**,完美解決「類方法訪問實例數據」的矛盾。網絡取消、配置管理、單例模擬、分類添加屬性等場景均可優雅落地。掌握關聯對象,是進階 iOS 開發的必修課。