Category (分類) 是 Objective-C 最獨特強大的特性之一,允許在不修改原始類別原始碼、不繼承的情況下,為現有類別動態新增方法。這對擴展系統框架類別 (如 NSString、NSArray、UIView) 極具價值。
// Girl+GirlCategory.h
#import "Girl.h"
@interface Girl (GirlCategory)
// 新增方法宣告
- (NSString *)showChineseName;
@end
// Girl+GirlCategory.m
#import "Girl+GirlCategory.h"
@implementation Girl (GirlCategory)
- (NSString *)showChineseName {
return @"美眉";
}
@end
原類別名+分類名.h/.m (如 Girl+GirlCategory.h)@interface 原類別 (分類名)@implementation 原類別 (分類名)| 特性 | Category (OC) | 繼承 (Subclass) | Extension Methods (C#) |
|---|---|---|---|
| 修改原始碼 | 不需要 | 不需要 | 不需要 |
| 新增實例變數 | ❌ 不支援 | ✅ 支援 | ❌ 不支援 |
| 覆寫現有方法 | ⚠️ 可能但危險 | ✅ 正規用途 | ❌ 不支援 |
| 編譯期類型檢查 | ✅ 完整 | ✅ 完整 | ✅ 完整 |
| 執行時解析 | 動態派發 | 動態派發 | 編譯期靜態 |
// 宣告符合協議 @interface Girl (GirlCategory)- (NSString *)showChineseName; @end
// Girl.m 頂部 @interface Girl () - (void)privateHelperMethod; @property (nonatomic, strong) NSString *internalCache; @end @implementation Girl // 私有方法實作與屬性自動合成 @end
#importstatic char ASSOCIATED_KEY; @implementation Girl (GirlCategory) - (void)setAssociatedName:(NSString *)name { objc_setAssociatedObject(self, &ASSOCIATED_KEY, name, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (NSString *)associatedName { return objc_getAssociatedObject(self, &ASSOCIATED_KEY); } @end
+ (void)load {
Method original = class_getInstanceMethod(self, @selector(originalMethod));
Method swizzled = class_getInstanceMethod(self, @selector(swizzledMethod));
method_exchangeImplementations(original, swizzled);
}
// NSString+Utilities.h @interface NSString (Utilities) - (BOOL)isValidEmail; - (NSString *)md5Hash; - (CGSize)sizeWithFont:(UIFont *)font maxWidth:(CGFloat)maxWidth; @end
// UIColor+Hex.h @interface UIColor (Hex) + (UIColor *)colorWithHexString:(NSString *)hexString; + (UIColor *)colorWithHexValue:(UInt32)hexValue alpha:(CGFloat)alpha; @end
xyz_showChineseName__weak typeof(self) weakSelf = self;#import "Class+Category.h"分類方法在執行時透過 objc_addClassMethods / objc_addInstanceMethods 合併到類別的方法列表中。載入順序:主類別 → 分類 (依編譯順序)。同名方法後載入者覆蓋先載入者,這也是衝突不可預測的原因。
Swift 的 extension 機制類似但更安全:
Category 是 Objective-C 動態特性的集中體現,善用它能讓程式碼更模組化、可維護。遵循「只增不改、加前綴、用關聯物件補足狀態」原則,即可安全發揮其最大價值。