1. 交換方法
1.1 獲取類方法
Method class_getClassMethod(Class cls , SEL name)
1.2 獲取實(shí)例方法
Method class_getInstanceMethod(Class cls , SEL name)
1.3 交換兩個(gè)方法
void method_exchangeImplementations(Method m1 , Method m2)
實(shí)例:
//Person.h
#import <Foundation/Foundation.h>
@interface Person : NSObject
+ (void)method_1;
+ (void)method_2;
- (void)method_3;
- (void)method_4;
@end
//Person.m
#import "Person.h"
@implementation Person
+ (void)method_1
{
NSLog(@"method_1");
}
+ (void)method_2
{
NSLog(@"method_2");
}
- (void)method_3
{
NSLog(@"method_3");
}
- (void)method_4
{
NSLog(@"emthod_4");
}
@end
[Person method_1]; //log: method_1
[Person method_2]; //log: method_2
Method m1 = class_getClassMethod([Person class], @selector(method_1));
Method m2 = class_getClassMethod([Person class], @selector(method_2));
method_exchangeImplementations(m1, m2);
[Person method_1]; //log: method_2
[Person method_2]; //log: method_1
Person *p = [[Person alloc] init];
[p method_3]; //log: method_3
[p method_4]; //log: method_4
Method m3 = class_getInstanceMethod([Person class], @selector(method_3));
Method m4 = class_getInstanceMethod([Person class], @selector(method_4));
method_exchangeImplementations(m3, m4);
[p method_3]; //log: method_4
[p method_4]; //log: method_3
2. 分類添加屬性
下面給NSObject添加一個(gè)name屬性
#import <Foundation/Foundation.h>
@interface NSObject (Category)
@property (nonatomic, strong) NSString *name;
@end
#import "NSObject+Category.h"
#import <objc/runtime.h>
const char * str = "myKey";
@implementation NSObject (Category)
- (void)setName:(NSString *)name
{
/**
* void objc_setAssociatedObject(id object , const void *key ,id value ,objc_AssociationPolicy policy)
* object 需要添加屬性的對(duì)象
* key 屬性的key, 將來(lái)可以通過key取出這個(gè)存儲(chǔ)的值
* value 屬性的值
* policy 使用的策略,是一個(gè)枚舉值僵缺,可根據(jù)開發(fā)需要選擇不同的枚舉
*/
objc_setAssociatedObject(self, &str, name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSString *)name
{
return objc_getAssociatedObject(self, &str);
}
@end
3. 消息攔截轉(zhuǎn)發(fā)
用到的幾個(gè)方法
+ (BOOL)resolveInstanceMethod:(SEL)sel
+ (BOOL)resolveClassMethod:(SEL)sel
- (id)forwardingTargetForSelector:(SEL)aSelector
- (void)forwardInvocation:(NSInvocation *)anInvocation
//對(duì)當(dāng)前類添加一個(gè)newTestMethod方法, 當(dāng)testMethod沒有實(shí)現(xiàn)時(shí), runtime會(huì)進(jìn)行消息轉(zhuǎn)發(fā)
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
// 指定對(duì)某一個(gè)方法的動(dòng)態(tài)解析
NSString *selName = NSStringFromSelector(sel);
if ([selName isEqualToString:@"testMethod"]) {
// 動(dòng)態(tài)的添加一個(gè)方法
class_addMethod([self class], @selector(testMethod), (IMP)newTestMethod, "v@:");
return YES;
}
return NO;
}
void newTestMethod()
{
NSLog(@"%s", __func__);
}
3.2 消息轉(zhuǎn)發(fā)到其他類
// 我們首先要通過, 指定方法簽名,若返回nil皿淋,則表示不處理谬盐。
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
NSLog(@"指定方法簽名");
NSString *selName = NSStringFromSelector(aSelector);
if ([selName isEqualToString:@"testMethod"]) {
return [NSMethodSignature signatureWithObjCTypes:"v@:"];
}
return [super methodSignatureForSelector:aSelector];
}
// 通過anInvocation對(duì)象做很多處理程剥,比如修改實(shí)現(xiàn)方法变过,修改響應(yīng)對(duì)象等
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
NSLog(@"%s", __func__);
// 改變響應(yīng)對(duì)象并改變響應(yīng)方法
[anInvocation setSelector:@selector(newTestMethod)];
[anInvocation invokeWithTarget:[ZYChildren new]];
}
//跳轉(zhuǎn)到其他類中執(zhí)行
- (id)forwardingTargetForSelector:(SEL)aSelector
{
NSLog(@"備用接收者");
// 指定對(duì)某一個(gè)對(duì)象來(lái)執(zhí)行方法
NSString *selName = NSStringFromSelector(aSelector);
if ([selName isEqualToString:@"testMethod"]) {
return [ZYChildren new];
}
return [super forwardingTargetForSelector:aSelector];;
}
//攔截調(diào)用
MyClass *myClass = [[MyClass alloc] init];
[myClass performSelector: @selector(testMethod) withObject: @"test"];
4. 其他用法
unsigned int count;
//獲取屬性列表
objc_property_t *propertyList = class_copyPropertyList([MyClass class], &count);
for (unsigned int i = 0; i < count; i ++)
{
const char *propertyName = property_getName(propertyList[i]);
NSLog(@"property ----> %@", [NSString stringWithUTF8String: propertyName]);
}
//獲取實(shí)例方法列表
Method *methodList = class_copyMethodList([MyClass class], &count);
for (unsigned int i = 0; i < count; i ++)
{
Method method = methodList[i];
NSLog(@"method ----> %@", NSStringFromSelector(method_getName(method)));
}
//獲取成員變量列表
Ivar *ivarList = class_copyIvarList([MyClass class], &count);
for (unsigned int i = 0; i < count; i ++)
{
Ivar myIvar = ivarList[i];
const char *ivarName = ivar_getName(myIvar);
NSLog(@"Ivar ----> %@", [NSString stringWithUTF8String: ivarName]);
}
//獲取協(xié)議列表
__unsafe_unretained Protocol **protocolList = class_copyProtocolList([MyClass class], &count);
for (unsigned int i = 0; i < count; i ++)
{
Protocol *myProtocal = protocolList[i];
const char *protocolName = protocol_getName(myProtocal);
NSLog(@"protocol ----> %@", [NSString stringWithUTF8String: protocolName]);
}