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

Objective-C 運行時關聯對象實戰:為類對象動態添加屬性解決網絡請求取消難題

     編輯:關於C語言

業務場景痛點

網絡層基類 `BaseNetwork` 派生多個子類(`LoginRequest`、`DataRequest` 等)。每個請求對象持有唯一 URL。需求:任意處調用**類方法** `[LoginRequest cancelAll]` 取消該類所有進行中請求,但類方法無法訪問實例屬性 `url`。

核心方案:objc_setAssociatedObject

利用 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++ 靜態成員變量

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,互不干擾

注意事項

  • Key 必須唯一,建議用 `static const char *` 或 `@selector(唯一名)`
  • 內存語義選擇:`RETAIN`/`COPY`/`ASSIGN` 對應強/複製/弱引用
  • 類對象生命周期 = App 進程生命周期,關聯對象隨進程釋放,無需手動清理
  • 線程安全:運行時內部加鎖,但業務邏輯若涉及讀寫競爭仍需自行同步

總結

`objc_setAssociatedObject` 是 Objective-C 動態性的強大體現,**為類對象添加「實例變量」**,完美解決「類方法訪問實例數據」的矛盾。網絡取消、配置管理、單例模擬、分類添加屬性等場景均可優雅落地。掌握關聯對象,是進階 iOS 開發的必修課。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved