// 今天來揭開神祕的Runtime機制的面紗。希望不侷限於會,最重要的是會用!!!!
先自己創建一個Dog 類
當然包含頭文件哈
#import <objc/runtime.h>
#import "TestRunTime-Swift.h"
- (void)viewDidLoad {
[superviewDidLoad];
////////////////////////////改變方法的實現 //////////////////////////
// 如果 msgSend(p1,s1)不能用配置settings enable ... objc_msgSend Calls ---NO
// objc_msgSend(self, @selector(askLog));
Method m1 =class_getInstanceMethod(self.class,@selector(askLog));
Method m2 =class_getInstanceMethod(self.class,@selector(answerLog));
method_exchangeImplementations(m1, m2);//交換兩個方法的實現
objc_msgSend(self,@selector(askLog));
// swift 需要預編譯一次
Animal * animal= [[Animalalloc]init];
[animal eat];
////////////////////////////// 動態添加方法 //////////////////////////
class_addMethod(animal.class,@selector(walk), (IMP)walk,"i@:");
[animal performSelector:@selector(walk)];
////////////////////////////////// 訪問成員變量 //////////////////////////
unsigned count =0;
Ivar * ivars =class_copyIvarList(animal.class, &count);
for (int i =0; i < count; i ++) {
// 保護指針指向的地址不被改變,即 s可以指向其他地址,但是 s[1] = "s";不行
constchar * s = ivar_getName(ivars[i]);
NSString * property = [NSStringstringWithCString:s encoding:NSUTF8StringEncoding];
NSLog(@" property = %@", property);
//kvo 賦值
[animal setValue:@"tomLI"forKey:property];
}
///////////////// valueForKeyPath 和 valueForKey的區別 ////////////////////////
NSDictionary * dict =@{@"one":@"1",
@"two":@{@"three":@"23"}
};
NSLog(@"value %@",[dictvalueForKeyPath:@"two.three"]);// 可以訪問到 23
NSLog(@"value %@",[dictvalueForKey:@"two.three"]); // 訪問不到 23,
NSLog(@"animal name = %@", animal.name);
// c 裏面的字符串定義。 cstr是一個指針
char * cstr ="sfg";
char cstrs[12] ="234abc";
NSLog(@"cstr = %s = cstrs = %s",cstr, cstrs);
/**
* _cmd在Objective-C的方法中表示當前方法的selector,正如同self表示當前方法調用的對象實例一樣。
*/
NSLog(@"_cmd %@",NSStringFromSelector(_cmd));
///////////////// 動態添加屬性 ////////////////////////
self.testName =@"這是動態添加的屬性";
NSLog(@"testName = %@",self.testName);
}
void walk(idself, SEL_cmd){
NSLog(@"給動物類添加走路的方法!!");
}
void add(idself, SEL_cmd){
NSLog(@"這是動態添加方法!");
}
- (void)askLog
{
NSLog(@"我是誰!!!");
}
- (void)answerLog
{
NSLog(@"我是你大爺");
}
static charconst * testNameKey = "testNameKey";
- (void)setTestName:(NSString*)name
{
/*
OBJC_ASSOCIATION_ASSIGN; //assign策略
OBJC_ASSOCIATION_COPY_NONATOMIC; //copy策略
OBJC_ASSOCIATION_RETAIN_NONATOMIC; // retain策略
OBJC_ASSOCIATION_RETAIN;
OBJC_ASSOCIATION_COPY;
*/
/*
* id object 給哪個對象的屬性賦值
const void *key 屬性對應的key
id value 設置屬性值爲value
objc_AssociationPolicy policy 使用的策略,是一個枚舉值,和copy,retain,assign是一樣的,手機開發一般都選擇NONATOMIC
objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);
*/
objc_setAssociatedObject(self,testNameKey, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString*)testName
{
return (NSString*)objc_getAssociatedObject(self,testNameKey);
}
輸出:
2017-04-25 10:22:19.331 TestRunTime[2370:333381] 我是你大爺
2017-04-25 10:22:19.332 TestRunTime[2370:333381] 我在吃東西!
2017-04-25 10:22:19.332 TestRunTime[2370:333381] 給動物類添加走路的方法!!
2017-04-25 10:22:19.332 TestRunTime[2370:333381] property = name
2017-04-25 10:22:19.333 TestRunTime[2370:333381] value 23
2017-04-25 10:22:19.333 TestRunTime[2370:333381] value (null)
2017-04-25 10:22:19.333 TestRunTime[2370:333381] animal name = tomLI
2017-04-25 10:22:19.333 TestRunTime[2370:333381] cstr = sfg = cstrs = 234abc
2017-04-25 10:22:19.333 TestRunTime[2370:333381] _cmd viewDidLoad
2017-04-25 10:22:19.333 TestRunTime[2370:333381] testName = 這是動態添加的屬性