Runtime 、 SEL and KVO

weixin_34162695發表於2018-05-15

一、SEL

1、什麼是SEL
@selector()就是取類方法的編號,他的行為基本可以等同C語言的中函式指標。

2、usage
宣告瞭一個函式指標myLog

@interface ViewController ()
{
    SEL myLog;
}
@end
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    myLog = @selector(myLogL);

    //通過performSelector來執行方法
   [self performSelector:myLog];//列印 “myLog”
}

-(void)myLogL{
    NSLog(@"myLog");
}

3、SEL的應用
target——action設計模式.

@interface Mybutton : UIButton
-(void)addMyTarget:(id)target action:(SEL)action;
@end


@implementation Mybutton
{
    SEL _action;
    id _target;
}

-(void)addMyTarget:(id)target action:(SEL)action{
    _target=target;
    _action=action;
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    [_target performSelector:_action];
}
 
@end

viewDidLoad:


- (void)viewDidLoad {

    [super viewDidLoad];
    Mybutton * btn = [[Mybutton alloc]initWithFrame:CGRectMake(100, 100, 60, 60)];
    btn.backgroundColor=[UIColor redColor];

    [btn addMyTarget:self action:@selector(click)];

    [self.view addSubview:btn];
}
 

-(void)click{
    NSLog(@"點選了btn");
}

二、Runtime

1、什麼是Runtime
RunTime簡稱執行時。
平時編寫的OC程式碼, 在程式執行過程中, 其實最終都是轉成了runtime的C語言程式碼。

需要匯入這兩個標頭檔案:

#import <objc/message.h>
#import <objc/runtime.h>

2、oc在向一個物件傳送訊息時,發生了什麼?
根據物件的isa指標找到類物件id,在查詢類物件裡面的methodLists方法函式列表,如果沒有找到,在沿著superClass, 尋找父類,再在父類methodLists方法列表裡面查詢,最終找到SEL,根據id和SEL確認IMP(指標函式),在傳送訊息;
IMP=implement

三、KVO

1、什麼是KVO
KVO(key-value-observing)是一種回撥機制,在某個物件註冊監聽者後,在被監聽的物件發生改變時,物件會傳送一個通知給監聽者,以便監聽者執行回撥操作
在 MVC 設計架構下的專案,KVO 機制很適合實現 mode 模型和 view 檢視之間的通訊。

2、pricinple
當觀察某物件 A 時,KVO 機制動態建立一個物件A當前類的子類,併為這個新的子類重寫了被觀察屬性 keyPath 的 setter 方法。setter 方法隨後負責通知觀察物件屬性的改變狀況。

3、usage
1)註冊觀察者

[self.myKVO addObserver:self forKeyPath:@"num" options:
NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil]; 
//第一個引數 observer:觀察者 (這裡觀察self.myKVO物件的屬性變化)
//第二個引數 keyPath: 被觀察的屬性名稱(這裡觀察 self.myKVO 中 num 屬性值的改變)
//第三個引數 options: 觀察屬性的新值、舊值等的一些配置(列舉值,可以根據需要設定,例如這裡可以使用兩項)
//第四個引數 context: 上下文,可以為 KVO 的回撥方法傳值(例如設定為一個放置資料的字典)
  1. 屬性(keyPath)的值發生變化時,收到通知,呼叫以下方法:
//aaa:屬性名稱
//bbb:被觀察的物件
//ccc:變化前後的值都儲存在 ccc 字典中
//ddd:註冊觀察者時,context 傳過來的值
-(void)observeValueForKeyPath:(NSString *)aaa   ofObject:(id)bbb  change:(NSDictionary<NSString *,id> *)ccc 
 context:(void *)ddd
{
}

4、例項

@implementation ViewController
- (void)viewDidLoad { 
[super viewDidLoad]; 
self.myKVO = [[myKVO alloc]init]; 

[self.myKVO addObserver:self  forKeyPath:@"num" options:
NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew  context:nil];
}

/*object的keyPath屬性發生變化,就會呼叫此回撥方法*/
-(void)observeValueForKeyPath:(NSString *)keyPath  ofObject:(id)object 
change:(NSDictionary<NSString *,id> *)change  context:(void *)context{


if([keyPath isEqualToString:@"num"] && object == self.myKVO) { 
// 響應變化處理:UI更新(label文字改變) 
}

- (void)didReceiveMemoryWarning { 
[super didReceiveMemoryWarning]; 
/* 移除KVO */ 
[self.myKVO removeObserver:self forKeyPath:@"num" context:nil];
}
@end

5、KVC與KVO
KVC 就是鍵值編碼(key-value-coding)。
KVC 的主要作用:
通過鍵值路徑為物件的屬性賦值。
通過鍵值路徑獲取屬性的值。

 [appleVC setValue:@"橘子" forKey:@"name"];
 
 //物件A的屬性是一個物件B,要設定物件B的屬性
 [person setValue:@"旺財" forKeyPath:@"dog.name"];

  NSString *nameStr = [appleVC valueForKey:@"name"];

例子:沒有辦法直接訪問內部

@implementation Person
{
  NSInteger _height;
}

- (void)logHeight
{    
  NSLog(@"%ld",_height);
}
@end


[p setValue:@170 forKey:@"height"];

KVO 就是基於 KVC 實現的關鍵技術之一。
KVO 的作用:它通過 key path 觀察物件的值,當值發生變化的時候會收到通知。

相關文章