前置準備
#import
// User 類別定義
@interface User : NSObject
@property (nonatomic, copy) NSString *userName;
- (id)initWithUserName:(NSString *)userName;
+ (id)userWithUserName:(NSString *)userName;
@end
一、類對象獲取與繼承關係
Class userClass = objc_getClass("User"); // 或 [User class]
Class superClass = class_getSuperclass(userClass); // NSObject
二、修改實例的類(isa 指向)
User *user = [User new];
Class original = object_setClass(user, [AnotherClass class]); // 替換 isa
// 原類別方法失效,新類別方法生效
三、類名轉換
const char *cName = class_getName(userClass); // "User"
NSString *name = NSStringFromClass(userClass); // @"User"
name = [NSString stringWithCString:cName encoding:NSUTF8StringEncoding];
四、屬性枚舉與存取
unsigned int count;
objc_property_t *props = class_copyPropertyList(userClass, &count);
for (i=0; i
五、方法操作大全
1. 列舉所有實例方法
Method *methods = class_copyMethodList(userClass, &count);
for (i=0; i
2. 獲取類/實例方法
SEL sel = sel_registerName("userWithUserName:");
Method clsMethod = class_getClassMethod(userClass, sel);
sel = sel_registerName("initWithUserName:");
Method instMethod = class_getInstanceMethod(userClass, sel);
3. 獲取實作 IMP
IMP imp = method_getImplementation(instMethod);
imp = class_getMethodImplementation(userClass, sel);
imp = [user methodForSelector:sel];
4. 動態新增方法
BOOL added = class_addMethod(userClass, @selector(newMethod:), (IMP)newMethodIMP, "v@:@");
if (added && class_respondsToSelector(userClass, @selector(newMethod:))) { … }
5. 方法交換
Method m1 = class_getInstanceMethod([self class], @selector(methodA));
Method m2 = class_getInstanceMethod([self class], @selector(methodB));
method_exchangeImplementations(m1, m2); // 交換 IMP
6. 方法替換
Method src = class_getInstanceMethod([self class], @selector(methodA));
IMP srcImp = method_getImplementation(src);
Method dst = class_getInstanceMethod([self class], @selector(methodB));
method_setImplementation(dst, srcImp); // dst 指向 src 實作
7. 方法覆蓋
IMP oldImp = class_replaceMethod(userClass, @selector(userName), (IMP)newUserNameIMP, "i@:@");
// 僅限全局函式實作,簽名必須一致
輸出範例
獲取所有方法
方法名:initWithUserName:; 返回類型@; 參數:@24@0:8@16
方法名:userName; 返回類型@; 參數:@16@0:8
方法名:setUserName:; 返回類型v; 參數:v24@0:8@16
方法交換前後
陽君 → IOS
IOS → 陽君
注意事項
- 所有
char* 均為 UTF-8 編碼。
- 動態修改類結構需謹慎,影響範圍全進程。
- ARC 環境下直接操作 Ivar 需特別小心記憶體管理。