前一篇博客最后介紹了KVC 再json 轉模型時遇到一些問題。今天接著來介紹KVC 的其他用法。其實我們在一開始的時候就一直再強調命名的重要性。命名規范是KVC 存活的基礎。如果沒有這個條件支撐,那么KVC使用起來就不會那么簡單了。在這里大王再嗶嗶幾句,作為一個程序員,不管我們長得有多丑,我們的代碼一定好看。一段規范的代碼代表我們的臉面,也是程序員成熟的標志。既然說到了命名,那么就再來看看KVC 讓人吃驚的一面。
1)KVC 方法的搜索順序
當你看到這個標題的時候,可能會詫異,說的是啥啊?啥是搜索順序啊?別著急,在介紹調用順序之前,我們先來看一段很簡單的代碼,先熱身一下。假設我們有一個Person類,這個類是個宅男,頭文件中啥玩意都沒有。既然頭文件中沒有任何屬性,我們就直接看實現文件。
#import "Person.h"@interface Person ()@PRoperty(nonatomic,copy)NSString* yourHand;@end@implementation Person-(instancetype)init{ self=[super init]; if (self) { self.yourHand=@"你的右手"; } return self;}-(NSString*)girlFriend{ NSLog(@"%s",__func__); return self.yourHand;}@end
為了防止宅男太過孤單,作為上帝的我,給他創建了手,并在一出生(init)時就給它賦值了。并且創建了一個girlFriend方法。如果我們想調用這個方法直接
[person girlFriend]是不行的(但是我們可以[person performSleector:@selector(girlFriend)],這是因為runtime的關系,這里不詳細介紹,可以參看我前幾篇博客),在這里,我們還可以這樣調用
- (void)viewDidLoad{ [super viewDidLoad]; Person *person=[[Person alloc] init]; NSLog(@"%@",[person valueForKey:@"girlFriend"]);}
2015-04-27 20:56:37.207 KVC[19591:953199] -[Person girlFriend]
2015-04-27 20:56:37.207 KVC[19591:953199] 你的右手
了解了上面的內容,我們就可以來說說KVC與容器類。什么是容器類呢?說簡單點就是數組和集合。這里沒啥可說的,還是先看代碼吧。還是這個Person類,我們先來稍微改動一下。頭文件還是什么都沒有,實現文件變為如下
#import "Person.h"@implementation Person-(NSUInteger)countOfFingers{ return 10;}-(id)objectInFingersAtIndex:(NSUInteger)index{ NSLog(@"這是第%lu個手指",index); return @(index);}@end
光看這段代碼不神奇,再看一下測試方法和打印信息,我們就會感到很吃驚。
- (void)viewDidLoad{ [super viewDidLoad]; Person *person=[[Person alloc] init]; NSLog(@"%@",[person valueForKey:@"fingers"]);}
2015-04-27 21:10:53.990 KVC[19658:958083] 這是第0個手指
2015-04-27 21:10:53.991 KVC[19658:958083] 這是第1個手指
2015-04-27 21:10:53.991 KVC[19658:958083] 這是第2個手指
2015-04-27 21:10:53.991 KVC[19658:958083] 這是第3個手指
2015-04-27 21:10:53.991 KVC[19658:958083] 這是第4個手指
2015-04-27 21:10:53.991 KVC[19658:958083] 這是第5個手指
2015-04-27 21:10:53.991 KVC[19658:958083] 這是第6個手指
2015-04-27 21:10:53.992 KVC[19658:958083] 這是第7個手指
2015-04-27 21:10:53.992 KVC[19658:958083] 這是第8個手指
2015-04-27 21:10:53.992 KVC[19658:958083] 這是第9個手指
2015-04-27 21:10:53.992 KVC[19658:958083] (
0,
1,
2,
3,
4,
5,
6,
7,
8,
9
)
全過程我們都沒有直接調用countOfFingers 和-(id)objectInFingersAtIndex:(NSUInteger)index 方法。由打印信息可以知道是系統幫我們調用了。并且有打印信息我們可以知道,系統把fingers 當成屬性,并且這個“屬性”是數組類型的。當我們調用valueForKey:時,系統會按如下順序調用方法
如果都找不到的話,系統會調用valueForUndefinedKey:方法。以上所講的都是針對不可變的容器類。如果是可變的容器類,我們可以可以這樣使用
dataM= [data mutbaleArrayValueForKey:@"屬性"]。當dataM改變的時候,會向data發送消息,data中的內容也會跟著改變。這里我就不詳細演示了,有興趣的可以自己試一下。
2)高階消息傳遞
大家可能冷不丁的看到高階這個詞感覺很高大上,仿佛又回到了大學的高數課堂。那么什么是高階消息傳遞呢?說白了就是讓數組中的每一個元素都執行某個方法,并把結果返回到新的數組中。這下感覺不那么高大上了吧?下面來看一個經典的例子代碼
- (void)viewDidLoad{ [super viewDidLoad]; NSArray *array=@[@"烤串",@"啤酒",@"爆米花"]; NSArray *lengths=[array valueForKeyPath:@"capitalizedString.length"]; NSLog(@"%@",lengths);}
2015-04-27 21:53:25.531 KVC[19821:972219] (
2,
2,
3
)
我們可以看出,數組中的每一項都執行了capitalizedString 方法,執行完后,又執行了length 方法。然后把結果返回到新的數組中。在開發中,我們可以適當的使用這個方法,會減少我們的代碼量。
盡管KVC很高大上,但是我們現實開發中,還是謹慎地使用,因為它太過于強大,貿然使用可能會無意間破壞程序的封裝性。所以我們只有想清楚了之后再使用,而且最好在使用的地方加上注釋。KVC 是大招,我們要在必要的時候使用,動畫片里孫悟空也不是在一開始就放大招,你說是不?
新聞熱點
疑難解答