在文章的最開始,先拋出三個問題:bash
對第一個問題,答案是NO,OC並不存在真正意義上的「私有變量」。咱們來看這樣的一段代碼:ui
//Teacher.h文件
@interface Teacher : NSObject
@end
//Teacher.m文件
@interface Teacher ()
{
@private NSInteger age; //age爲Teacher類的私有變量
}
@end
@implementation Teacher
- (instancetype)init{
if (self = [super init]) {
age = 10;
}
return self;
}
@end
複製代碼
Teacher類中存在一個私有變量age,在Teacher的init方法中設置age=10,照理說這個age外界是沒法訪問的,這一點也符合面嚮對象語言的封裝特性,可是(永遠有個可是,敲黑板了,這裏是重點),使用KVC技術,咱們能夠打破封裝特性,代碼以下:spa
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
Teacher *t = [Teacher new];
NSLog(@"teacher's age = %@", [t valueForKey:@"age"]);
}
@end
複製代碼
運行程序,而後咱們看一下打印結果:code
結論1:只要咱們知道私有成員變量的名字並結合KVC技術,在OC的世界裏,根本沒有「祕密」😅cdn
雖然KVC的確把面嚮對象語言撕開了一道口子,可是換個角度想,這道口子同時也給iOS開發者提供了必定的便利性。也就是說,KVC其實是一把雙刃劍,用得好,能夠在特定場景下爲咱們高效解決需求,用得很差,後果一樣可怕。對象
例如,當我嘗試用KVC訪問Teacher類中並不存在的變量「gender」時,程序直接Crash了: blog
咱們分析一下這個Crash,發現是**valueForUndefinedKey:**方法拋出的異常,咱們試着來實現一下這個系統方法,不妨先返回nil,而後再運行一次: 開發
這一次系統沒有Crash,並且gender打印了(null)。從結果上能夠看出,當KVC找不到gender這個值時,會來到valueForUndefinedKey:方法,給咱們最後一次機會,只要咱們返回一個值來回應KVC對gender的訪問,即使是返回nil,系統也不至於Crash。get
結論2:KVC是一把雙刃劍,有利也有弊,經過重寫valueForUndefinedKey:方法,能夠規避使用KVC的弊端string
字不如圖,咱們直接看KVC的調用流程圖:
前面的解釋裏,我屢次用了「符合條件」這個詞,怎麼理解?仍是用圖說話,KVC會按照下圖所示的格式,逐一去尋找對應的方法或者成員變量,感興趣的能夠本身寫個demo試試看。
結論3:KVC的調用流程分三步走,先找方法,再找成員變量,最終還找不到,就直接調用valueForUndefinedKey:來拋出異常。