KVC和KVO

OC中的一個比較有特色的知識點:KVC和KVO

一、KVC操作
OC中的KVC操作就和Java中使用反射機制去訪問類的private權限的變量,很暴力的,這樣做就會破壞類的封裝性,本來類中的的private權限就是不希望外界去訪問的,但是我們這樣去操作,就會反其道而行,但是我們有時候真的需要去這樣做,哎。所以說有些事不是都是順其自然的,而是需要的時候自然就誕生了。
下面就來看一下這種技術的使用:
Dog.h
[objc]??view plaincopy
1. //??
2. //??Dog.h??
3. //??42_KVC??
4. //??
5. //??Created?by?jiangwei?on?14-10-14.??
6. //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.??
7. //??
8. ??
9. #import?<Foundation/Foundation.h>??
10. ??
11. @interface?Dog?:?NSObject??
12. ??
13. @end??


Dog.m
[objc]??view plaincopy
1. //??
2. //??Dog.m??
3. //??42_KVC??
4. //??
5. //??Created?by?jiangwei?on?14-10-14.??
6. //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.??
7. //??
8. ??
9. #import?"Dog.h"??
10. ??
11. @implementation?Dog??
12. ??
13. @end??
定義了Dog這個類,但是什么都沒有,他只是一個中間類,沒什么作用,在這個demo中。


Person.h
[objc]??view plaincopy
1. //??
2. //??Person.h??
3. //??42_KVC??
4. //??
5. //??Created?by?jiangwei?on?14-10-14.??
6. //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.??
7. //??
8. ??
9. #import?<Foundation/Foundation.h>??
10. #import?"Dog.h"??
11. ??
12. @interface?Person?:?NSObject{??
13. @private??
14. ????NSString?*_name;??
15. ????NSDog?*_dog;??
16. ??????
17. ????NSInteger?*age;??
18. }??
19. ??
20. @end??


Person.m
[objc]??view plaincopy
1. //??
2. //??Person.m??
3. //??42_KVC??
4. //??
5. //??Created?by?jiangwei?on?14-10-14.??
6. //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.??
7. //??
8. ??
9. #import?"Person.h"??
10. ??
11. @implementation?Person??
12. ??
13. -?(NSString?*)description{??
14. ????NSLog(@"%@",_name);??
15. ????return?_name;??
16. }??
17. ??
18. @end??
Person類中我們定義了兩個屬性,但是這兩個屬性對外是不可訪問的,而且也沒有對應的get/set方法。我們也實現了description方法,用于打印結果


看一下測試代碼
main.m
[objc]??view plaincopy
1. //??
2. //??main.m??
3. //??42_KVC??
4. //??
5. //??Created?by?jiangwei?on?14-10-14.??
6. //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.??
7. //??
8. ??
9. #import?<Foundation/Foundation.h>??
10. #import?"Person.h"??
11. #import?"Dog.h"??
12. ??
13. //KVC:很暴力,及時一個類的屬性是私有的,而且也沒有get/set方法,同樣可以讀寫??
14. //相當于Java中的反射,破壞類的封裝性??
15. int?main(int?argc,?const?charchar?*?argv[])?{??
16. ????@autoreleasepool?{??
17. ??????????
18. ????????Person?*p?=?[[Person?alloc]?init];??
19. ??????????
20. ????????//設置值??
21. ????????//這里setValue方法:第一個參數是value,第二個參數是key(就是類的屬性名稱)??
22. ????????[p?setValue:@"jiangwei"?forKey:@"name"];??
23. ??????????
24. ????????Dog?*dog?=?[[Dog?alloc]?init];??
25. ????????[p?setValue:dog?forKey:@"dog"];??
26. ??????????
27. ????????//KVC設置值時,如果屬性有set方法,則優先調用set方法,如果沒有則直接設置上去,get方法類似??
28. ??????????
29. ????????//讀取值??
30. ????????NSString?*name?=?[p?valueForKey:@"name"];??
31. ??????????
32. ????????//設置基本數據類型??
33. ????????//這里需要將基本類型轉化成NSNumber??
34. ????????//在設置值的時候,會有自動解包的過程,NSNumber會解包賦值給age??
35. ????????[p?setValue:@22?forKey:@"age"];??
36. ??????????
37. ????????NSLog(@"%@",p);??
38. ??????????
39. ????????return?0;??
40. ????}??
41. ????return?0;??
42. }??
這里我們生成一個Person對象,然后開始使用KVC技術了:


1、設置屬性值
[java]??view plaincopy
1. //設置值??
2. //這里setValue方法:第一個參數是value,第二個參數是key(就是類的屬性名稱)??
3. [p?setValue:@"jiangwei"?forKey:@"name"];??
4. ??????????
5. Dog?*dog?=?[[Dog?alloc]?init];??
6. [p?setValue:dog?forKey:@"dog"];??
使用setValue方法,就可以進行對屬性進行設置值操作了,同時需要傳遞這個屬性的名稱,這個和Java中使用反射機制真的很像。
注:KVC設置值時,如果屬性有set方法,則優先調用set方法,如果沒有則直接設置上去,get方法一樣
[java]??view plaincopy
1. //設置基本數據類型??
2. //這里需要將基本類型轉化成NSNumber??
3. //在設置值的時候,會有自動解包的過程,NSNumber會解包賦值給age??
4. [p?setValue:@22?forKey:@"age"];??
還有一個需要注意的地方:當我們在設置基本類型的時候,需要將其轉化成NSNumber類型的。


2、取屬性的值
[java]??view plaincopy
1. //讀取值??
2. NSString?*name?=?[p?valueForKey:@"name"];??
取值就簡單了

下面再來看一下KVC中強大的功能:鍵值路徑
鍵值路徑是對于一個類中有數組對象的屬性進行便捷操作。
看個場景:
一個作者有多本書
Author.h
[objc]??view plaincopy
1. //??
2. //??Author.h??
3. //??43_KeyValuePath??
4. //??
5. //??Created?by?jiangwei?on?14-10-15.??
6. //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.??
7. //??
8. ??
9. #import?<Foundation/Foundation.h>??
10. ??
11. @interface?Author?:?NSObject{??
12. ????NSString?*_name;??
13. ??????
14. ????//作者出版的書,一個作者對應多個書籍對象??
15. ????NSArray?*_issueBook;??
16. }??
17. ??
18. @end??
作者類中定義了名字和一個書籍數組

Author.m
[objc]??view plaincopy
1. //??
2. //??Author.m??
3. //??43_KeyValuePath??
4. //??
5. //??Created?by?jiangwei?on?14-10-15.??
6. //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.??
7. //??
8. ??
9. #import?"Author.h"??
10. ??
11. @implementation?Author??
12. ??
13. @end??

Book.h
[objc]??view plaincopy
1. //??
2. //??Book.h??
3. //??43_KeyValuePath??
4. //??
5. //??Created?by?jiangwei?on?14-10-15.??
6. //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.??
7. //??
8. ??
9. #import?<Foundation/Foundation.h>??
10. #import?"Author.h"??
11. ??
12. @interface?Book?:?NSObject{??
13. ????Author?*_author;??
14. }??
15. ??
16. @property?NSString?*name;??
17. @property?floatfloat?*price;??
18. ??
19. @end??
定義了一個作者屬性,書的名字,價格

Book.m
[objc]??view plaincopy
1. //??
2. //??Book.m??
3. //??43_KeyValuePath??
4. //??
5. //??Created?by?jiangwei?on?14-10-15.??
6. //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.??
7. //??
8. ??
9. #import?"Book.h"??
10. ??
11. @implementation?Book??
12. ??
13. @end??

看一下測試代碼
main.m
[objc]??view plaincopy
1. //??
2. //??main.m??
3. //??43_KeyValuePath??
4. //??
5. //??Created?by?jiangwei?on?14-10-15.??
6. //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.??
7. //??
8. ??
9. #import?<Foundation/Foundation.h>??
10. #import?"Book.h"??
11. #import?"Author.h"??
12. ??
13. int?main(int?argc,?const?charchar?*?argv[])?{??
14. ????@autoreleasepool?{??
15. ??????????
16. ????????//------------------KVC鍵值路徑??
17. ????????/*?
18. ????????Book?*book?=?[[Book?alloc]?init];?
19. ????????Author?*author?=?[[Author?alloc]?init];?
20. ?????????
21. ????????//設置作者?
22. ????????[book?setValue:author?forKey:@"author"];?
23. ?????????
24. ????????//設置作者的名字?
25. ????????//路徑為:author.name,中間用點號進行連接?
26. ????????[book?setValue:@"jiangwei"?forKeyPath:@"author.name"];?
27. ????????NSString?*name?=?[author?valueForKey:@"name"];?
28. ????????NSLog(@"name?is?%@",name);?
29. ?????????*/??
30. ??????????
31. ??????????
32. ????????//--------------------KVC的運算??
33. ????????Author?*author?=?[[Author?alloc]?init];??
34. ????????[author?setValue:@"莫言"?forKeyPath:@"name"];??
35. ??????????
36. ????????Book?*book1?=?[[Book?alloc]?init];??
37. ????????book1.name?=?@"紅高粱";??
38. ????????book1.price?=?9;??
39. ????????Book?*book2?=?[[Book?alloc]?init];??
40. ????????book2.name?=?@"蛙";??
41. ????????book2.price?=?10;??
42. ????????NSArray?*array?=?[NSArray?arrayWithObjects:book1,book2,?nil?nil];??
43. ????????[author?setValue:array?forKeyPath:@"issueBook"];??
44. ??????????
45. ????????//基本數據類型會自動被包裝成NSNumber,裝到數組中??
46. ????????//得到所有書籍的價格??
47. ????????NSArray?*priceArray?=?[author?valueForKeyPath:@"issueBook.price"];??
48. ????????NSLog(@"%@",priceArray);??
49. ??????????
50. ????????//獲取數組的大小??
51. ????????NSNumber?*count?=?[author?valueForKeyPath:@"issueBook.@count"];??
52. ????????NSLog(@"count=%@",count);??
53. ??????????
54. ????????//獲取書籍價格的總和??
55. ????????NSNumber?*sum?=?[author?valueForKeyPath:@"issueBook.@sum.price"];??
56. ????????NSLog(@"%@",sum);??
57. ??????????
58. ????????//獲取書籍的平均值??
59. ????????NSNumber?*avg?=?[author?valueForKeyPath:@"issueBook.@avg.price"];??
60. ????????NSLog(@"%@",avg);??
61. ??????????
62. ????????//獲取書籍的價格最大值和最小值??
63. ????????NSNumber?*max?=?[author?valueForKeyPath:@"issueBook.@max.price"];??
64. ????????NSNumber?*min?=?[author?valueForKeyPath:@"issueBook.@min.price"];??
65. ??????????
66. ????}??
67. ????return?0;??
68. }??

1、首先通過前面說到的KVC設置作者的書籍數組
[objc]??view plaincopy
1. //--------------------KVC的運算??
2. Author?*author?=?[[Author?alloc]?init];??
3. [author?setValue:@"莫言"?forKeyPath:@"name"];??
4. ??
5. Book?*book1?=?[[Book?alloc]?init];??
6. book1.name?=?@"紅高粱";??
7. book1.price?=?9;??
8. Book?*book2?=?[[Book?alloc]?init];??
9. book2.name?=?@"蛙";??
10. book2.price?=?10;??
11. NSArray?*array?=?[NSArray?arrayWithObjects:book1,book2,?nil?nil];??
12. [author?setValue:array?forKeyPath:@"issueBook"];??
添加了兩本書籍

2、下面就開始用到KVC中鍵值路徑了
1)獲取作者類中書籍數組中所有書籍的價格
[java]??view plaincopy
1. //基本數據類型會自動被包裝成NSNumber,裝到數組中??
2. //得到所有書籍的價格??
3. NSArray?*priceArray?=?[author?valueForKeyPath:@"issueBook.price"];??
4. NSLog(@"%@",priceArray);??
看到了:@"issueBook.price" 這就是鍵值路徑的使用,issueBook是作者類中的書籍數組屬性名,price是書籍類的屬性,中間用點號進行連接,這樣我們就可以獲取到了所有書籍的價格了,如果在Java中,我們需要用一個循環操作。但是OC中多么方便。

2)獲取作者類中書籍數組的大小
[java]??view plaincopy
1. //獲取數組的大小??
2. NSNumber?*count?=?[author?valueForKeyPath:@"issueBook.@count"];??
3. NSLog(@"count=%@",count);??
使用 @"issueBook.@count" 鍵值路徑獲取書籍數組的大小,issueBook是作者類中的書籍數組屬性名,@count是特定一個寫法,可以把它想象成一個方法,中間任然用點號進行連接

3)獲取作者類中書籍數組的價格總和
[java]??view plaincopy
1. //獲取書籍價格的總和??
2. NSNumber?*sum?=?[author?valueForKeyPath:@"issueBook.@sum.price"];??
3. NSLog(@"%@",sum);??
使用 @"issueBook.@sum.price" 鍵值路徑獲取書籍數組中的價格總和,issueBook是作者類中的書籍數組屬性名,@sum是特性寫法,可以把它想象成一個方法,price是書籍的價格屬性名,可以把它看成是@sum的一個參數,中間用點號進行連接
如果在java中,這個需要用一個循環來計算總和,OC中很方便的

4)獲取作者類中書籍數組的價格平均值、最小值、最大值
[objc]??view plaincopy
1. //獲取書籍的平均值??
2. NSNumber?*avg?=?[author?valueForKeyPath:@"issueBook.@avg.price"];??
3. NSLog(@"%@",avg);??
4. ??
5. //獲取書籍的價格最大值和最小值??
6. NSNumber?*max?=?[author?valueForKeyPath:@"issueBook.@max.price"];??
7. NSNumber?*min?=?[author?valueForKeyPath:@"issueBook.@min.price"];??
操作和上面類似,這里就不解釋了

我們看到上面返回來的數據都是NSNumber類型的

二、KVO操作
KVO操作在OC中也是經常會用到的,而且這種機制在java中不存在的。
它的作用就是用來監聽類中屬性值的變化,實現原理是觀察者模式,當然我們也可以使用觀察者模式在Java中實現這樣的機制
看一下具體的例子:現在有一個小孩類,他有兩個屬性:開心值,饑餓值,然后還有一個護士類,用來監聽孩子類的這兩個屬性值的
Chidren.h
[objc]??view plaincopy
1. //??
2. //??Children.h??
3. //??44_KVO??
4. //??
5. //??Created?by?jiangwei?on?14-10-16.??
6. //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.??
7. //??
8. ??
9. #import?<Foundation/Foundation.h>??
10. ??
11. @interface?Children?:?NSObject??
12. ??
13. @property?NSInteger?*hapyValue;??
14. @property?NSInteger?*hurryValue;??
15. ??
16. ??
17. @end??

Children.m
[objc]??view plaincopy
1. //??
2. //??Children.m??
3. //??44_KVO??
4. //??
5. //??Created?by?jiangwei?on?14-10-16.??
6. //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.??
7. //??
8. ??
9. #import?"Children.h"??
10. ??
11. @implementation?Children??
12. ??
13. -?(id)?init{??
14. ????self?=?[super?init];??
15. ????if(self?!=?nil){??
16. ????????//啟動定時器??
17. ????????[NSTimer?scheduledTimerWithTimeInterval:1?target:self?selector:@selector(timerAction)?userInfo:nil?repeats:YES];??
18. ????????self.hapyValue=?100;??
19. ????}??
20. ????return?self;??
21. }??
22. ??
23. -?(void)?timerAction:(NSTimer?*)?timer{??
24. ????//使用set方法修改屬性值,才能觸發KVO??
25. ??????
26. ????int?value?=?_hapyValue;??
27. ????[self?setHapyValue:--value];??
28. ??????
29. ????int?values?=?_hurryValue;??
30. ????[self?setHurryValue:--values];??
31. }??
32. ??
33. ??
34. @end??
在初始化方法中,我們啟動一個定時器,然后隔1s就去修改孩子類的值

Nure.h
[objc]??view plaincopy
1. //??
2. //??Nure.h??
3. //??44_KVO??
4. //??
5. //??Created?by?jiangwei?on?14-10-16.??
6. //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.??
7. //??
8. ??
9. #import?<Foundation/Foundation.h>??
10. ??
11. @class?Children;??
12. @interface?Nure?:?NSObject{??
13. ????Children?*_children;??
14. }??
15. ??
16. -?(id)?initWithChildren:(Children?*)children;??
17. ??
18. @end??
定義一個孩子屬性


Nure.m
[objc]??view plaincopy
1. //??
2. //??Nure.m??
3. //??44_KVO??
4. //??
5. //??Created?by?jiangwei?on?14-10-16.??
6. //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.??
7. //??
8. ??
9. #import?"Nure.h"??
10. #import?"Children.h"??
11. ??
12. @implementation?Nure??
13. ??
14. -?(id)?initWithChildren:(Children?*)children{??
15. ????self?=?[super?init];??
16. ????if(self?!=?nil){??
17. ????????_children?=?children;??
18. ??????????
19. ????????//觀察小孩的hapyValue??
20. ????????//使用KVO為_children對象添加一個觀察者,用于觀察監聽hapyValue屬性值是否被修改??
21. ????????[_children?addObserver:self?forKeyPath:@"hapyValue"?options:NSKeyValueObservingOptionNew?|NSKeyValueObservingOptionOld?context:@"context"];??
22. ??????????
23. ????????//觀察小孩的hurryValue??
24. ????????[_children?addObserver:self?forKeyPath:@"hurryValue"?options:NSKeyValueObservingOptionNew?|NSKeyValueObservingOptionOld?context:@"context"];??
25. ????}??
26. ????return?self;??
27. }??
28. ??
29. //觸發方法??
30. -?(void)observeValueForKeyPath:(NSString?*)keyPath?ofObject:(id)object?change:(NSDictionary?*)change?context:(voidvoid?*)context{??
31. ????NSLog(@"%@",change);??
32. ????//通過打印change,我們可以看到對應的key??
33. ??????
34. ????//通過keyPath來判斷不同屬性的觀察者??
35. ????if([keyPath?isEqualToString:@"hapyValue"]){??
36. ????????//這里change中有old和new的值是因為我們在調用addObserver方法時,用到了??
37. ????????//NSKeyValueObservingOptionNew?|?NSKeyValueObservingOptionOld;想要哪一個就用哪一個??
38. ????????//[change?objectForKey:@"old"]是修改前的值??
39. ????????NSNumber?*hapyValue?=?[change?objectForKey:@"new"];//修改之后的最新值??
40. ??????????
41. ????????NSInteger?*value?=?[hapyValue?integerValue];??
42. ??????????
43. ????????if(value?<?90){??
44. ????????????//do?something...??
45. ????????}??
46. ????}else?if([keyPath?isEqualToString:@"hurryValue"]){??
47. ????????//這里change中有old和new的值是因為我們在調用addObserver方法時,用到了??
48. ????????//NSKeyValueObservingOptionNew?|?NSKeyValueObservingOptionOld;想要哪一個就用哪一個??
49. ????????//[change?objectForKey:@"old"]是修改前的值??
50. ????????NSNumber?*hurryValue?=?[change?objectForKey:@"new"];//修改之后的最新值??
51. ??????????
52. ????????NSInteger?*value?=?[hurryValue?integerValue];??
53. ??????????
54. ????????if(value?<?90){??
55. ????????????//do?something...??
56. ????????}??
57. ????}??
58. ??????
59. ????NSLog(@"%@",context);//打印的就是addObserver方法的context參數??
60. ??????
61. ??????
62. ??????
63. ????//使用KVC去修改屬性的值,也會觸發事件??
64. }??
65. ??
66. -?(void)dealloc{??
67. ??????
68. ????//移除觀察者??
69. ????[_children?removeObserver:self?forKeyPath:@"hapyValue"];??
70. ????[_children?removeObserver:self?forKeyPath:@"hurryValue"];??
71. ??????
72. }??
73. ??
74. @end??
看到了在這里就開始進行監聽操作了

下面來具體看一下如何做到監聽的
1、添加監聽對象
我們使用addObserver方法給孩子添加監聽對象
第一個參數:監聽者,這里是Nure,所以可以直接傳遞self
第二個參數:監聽對象的屬性名
第三個參數:監聽這個屬性的狀態:這里可以使用|進行多種組合操作,屬性的新值和舊值
第四個參數:傳遞內容給監聽方法
[java]??view plaincopy
1. //觀察小孩的hapyValue??
2. //使用KVO為_children對象添加一個觀察者,用于觀察監聽hapyValue屬性值是否被修改??
3. [_children?addObserver:self?forKeyPath:@"hapyValue"?options:NSKeyValueObservingOptionNew?|NSKeyValueObservingOptionOld?context:@"context"];??
4. ??
5. //觀察小孩的hurryValue??
6. [_children?addObserver:self?forKeyPath:@"hurryValue"?options:NSKeyValueObservingOptionNew?|NSKeyValueObservingOptionOld?context:@"context"];??

2、監聽方法
[objc]??view plaincopy
1. //觸發方法??
2. -?(void)observeValueForKeyPath:(NSString?*)keyPath?ofObject:(id)object?change:(NSDictionary?*)change?context:(voidvoid?*)context{??
3. ????NSLog(@"%@",change);??
4. ????//通過打印change,我們可以看到對應的key??
5. ??????
6. ????//通過keyPath來判斷不同屬性的觀察者??
7. ????if([keyPath?isEqualToString:@"hapyValue"]){??
8. ????????//這里change中有old和new的值是因為我們在調用addObserver方法時,用到了??
9. ????????//NSKeyValueObservingOptionNew?|?NSKeyValueObservingOptionOld;想要哪一個就用哪一個??
10. ????????//[change?objectForKey:@"old"]是修改前的值??
11. ????????NSNumber?*hapyValue?=?[change?objectForKey:@"new"];//修改之后的最新值??
12. ??????????
13. ????????NSInteger?*value?=?[hapyValue?integerValue];??
14. ??????????
15. ????????if(value?<?90){??
16. ????????????//do?something...??
17. ????????}??
18. ????}else?if([keyPath?isEqualToString:@"hurryValue"]){??
19. ????????//這里change中有old和new的值是因為我們在調用addObserver方法時,用到了??
20. ????????//NSKeyValueObservingOptionNew?|?NSKeyValueObservingOptionOld;想要哪一個就用哪一個??
21. ????????//[change?objectForKey:@"old"]是修改前的值??
22. ????????NSNumber?*hurryValue?=?[change?objectForKey:@"new"];//修改之后的最新值??
23. ??????????
24. ????????NSInteger?*value?=?[hurryValue?integerValue];??
25. ??????????
26. ????????if(value?<?90){??
27. ????????????//do?something...??
28. ????????}??
29. ????}??
30. ??????
31. ????NSLog(@"%@",context);//打印的就是addObserver方法的context參數??
32. ??????
33. ??????
34. ??????
35. ????//使用KVC去修改屬性的值,也會觸發事件??
36. }??
我們上面傳遞的第一個參數是監聽者,這個方法也是在監聽者中實現的,當屬性值發生變化的時候,這個方法會被回調
這個方法的參數:
第一個參數:鍵值路徑
第二個參數:監聽對象
第三個參數:變化的值
第四個參數:傳遞的內容
我們看到代碼中有一個特殊的參數:第三個參數:NSDirctionary類型的
其實我們如果不知道是干什么的,我們可以打印一下他的結果看一下,很簡單,這里就不截圖說明了
我們會發現他有兩個鍵值對
key是:new和old
他們就是分別代表這個屬性值變化的前后值,同時他們的得到也和之前我們添加監聽對象時設置的第三個參數有關:
NSKeyValueObservingOptionNew?|NSKeyValueObservingOptionOld
那個地方設置了幾種狀態,這里的NSDirctionary中就會有幾個鍵值對

3、銷毀方法
這個并不屬于KVO的內容了,只是在這里用到了就順便說一下
[objc]??view plaincopy
1. -?(void)dealloc{??
2. ??????
3. ????//移除觀察者??
4. ????[_children?removeObserver:self?forKeyPath:@"hapyValue"];??
5. ????[_children?removeObserver:self?forKeyPath:@"hurryValue"];??
6. ??????
7. }??
我們在創建一個對象的時候會調用alloc方法,當對象被銷毀的時候會調用dealloc這個方法,這個和C++中的析構函數一樣,Java中有垃圾回收器,所以沒有此類的方法,但是有一個finalize方法,其實這個方法就是在垃圾回收器回收對象的時候會調用,和這個功能差不多,但是在Java中,我們并不提倡使用這個方法。因為會造成GC的回收發生錯誤。
我們在銷毀方法中需要移除監聽者

總結
這一篇就介紹了OC中比較有特色的兩個機制:KVC和KVO
KVC:就是可以暴力的去get/set類的私有屬性,同時還有強大的鍵值路徑對數組類型的屬性進行操作
KVO:監聽類中屬性值變化的

轉載于:https://www.cnblogs.com/GhostKZShadow/p/5105176.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/375210.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/375210.shtml
英文地址,請注明出處:http://en.pswp.cn/news/375210.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

8086加法指令ADD

加法指令ADD(ADDition) ADD OPRD1,OPRD2 ;OPRD1<--OPRD1OPRD2 ;完成OPRD1與OPRD2相加 ,結果保存在OPRD1中CODE SEGMENT MOV AX,1 MOV BX,2 ADD AX,BX ;AX<--AXBX ,結果AX3CODE ENDS參與運算的操作數類型必須保持一致,同為字節或字可組合以下幾種形式&…

Fragment基礎講解

//新建一個碎片public class LeftFragment extends Fragment { Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // 加載一個碎片界面 View view inflater.inflate(R.layout.leftfragment, container, false)…

[bzoj1012](JSOI2008)最大數maxnumber(Fenwick Tree)

Description 現在請求你維護一個數列&#xff0c;要求提供以下兩種操作&#xff1a; 1、 查詢操作。語法&#xff1a;Q L 功能&#xff1a;查詢當前數列中末尾L個數中的最大的數&#xff0c;并輸出這個數的值。限制&#xff1a;L不超過當前數列的長度。 2、 插入操作。語法&…

javaScript轉換日期合格式

javascript如何將時間日期轉換為Date對象:有時候需要講一個字符串型的時間日期轉換為Date時間對象&#xff0c;下面就通過一個簡單的實例提供一種解決方案&#xff0c;當然也是一種思路&#xff0c;可以進行一定的變通&#xff0c;以達到舉一反三的效果。例如這里有一個時間日期…

8086減法指令SUB

減法指令SUB(SUBtraction) SUB OPRD1,OPRD2 ; OPRD1<-- OPRD1-OPRD2 都影響FLAG標志寄存器,同樣的包含兩種含義(有符號減法和無符號減法)

奇怪吸引子---Dadras

奇怪吸引子是混沌學的重要組成理論&#xff0c;用于演化過程的終極狀態&#xff0c;具有如下特征&#xff1a;終極性、穩定性、吸引性。吸引子是一個數學概念&#xff0c;描寫運動的收斂類型。它是指這樣的一個集合&#xff0c;當時間趨于無窮大時&#xff0c;在任何一個有界集…

8086 INC, DEC

INC OPRD ;OPRD<--OPRD1 ;自加1指令code segmentmov ax,0inc ax ;ax<--ax1 ,ax1inc ax ;ax<--ax1 ,ax2code endsDEC OPRD ;OPRD<--OPRD-1 ;自減1指令code segmentmov ax,5dec ax ;ax<--ax-1 ,ax4 code ends

iPhone UITableViewCell如何滾動到視圖頂端。

如何讓UITableViewCell滾動到視圖頂端。 - (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated;- (void)scrollToNearestSelectedRowAtScrollPosition:(UITableViewScrollPosition)s…

app 一些常用的

發短信 &#xff1a;sms:10086 打電話&#xff1a;tel:10086 1、-webkit-tap-highlight-color:rgba(255,255,255,0)可以同時屏蔽ios和android下點擊元素時出現的陰影。備注&#xff1a;transparent的屬性值在android下無效。 2、-webkit-appearance:none可以同時屏蔽輸入框怪異…

8086乘法指令MUL,IMUL

對于加減指令來說CPU對有符號加減和無符號加減一視同仁,根據我們需要把它作為有符號的結果還是無符號的結果,但是乘除法指令區分有符號乘除和無符號乘除指令 無符號數乘法指令MUL(MULtiply) MUL OPRD(OPRD可以用除立即數以外的任何尋址方式)OPRD是八位一個乘數默認在AL中 則&am…

hdu 4857 逃生 拓撲排序

逃生題目連接&#xff1a; http://acm.hdu.edu.cn/showproblem.php?pid4857 Description 糟糕的事情發生啦&#xff0c;現在大家都忙著逃命。但是逃命的通道很窄&#xff0c;大家只能排成一行。 現在有n個人&#xff0c;從1標號到n。同時有一些奇怪的約束條件&#xff0c;每個…

指針數組,數組指針,指針函數,函數指針(轉)

int *p[4]; //指針數組。 是個有4個元素的數組&#xff0c; 每個元素的是指向整型的指針。(數組的每個元素都是指針)int (*p)[4]; //數組指針。 它是一個指針&#xff0c;指向有4個整型元素的數組。 (一個指針指向有4個整型元素的數組)int *…

8086除法指令DIV,IDIV

無符號除法指令DIV(DIVision) DIV OPRD ;除數OPRD決定是8位除法還是16位除法;OPRD8位,則被除數默認在AX中,AX除以OPRD的商保存在AL中,余數保存在AH中;OPRD16位,則被除數默認在DX與AX中,結果的商保存在AX中,余數保存到DX中assume cs:code data segmentdb 2,4 data ends code se…

Hibernate 基礎配置及常用功能(二)

本章主要是描述幾種經典映射關系&#xff0c;順帶比較Hibernate4.x和Hibernate5.x之間的區別。 一、建立測試工程目錄 有關實體類之間的相互映射關系&#xff0c;Hibernate官方文檔其實描述的非常詳細&#xff0c;這里只提供幾種常見映射。&#xff08;推薦4.3.11版本的 hibern…

三言兩語

人生中總是在選擇。每當做一件事我們都應該問問我們的內心&#xff0c;或多或少我們都能理解一點人生的真諦。 最近時間很充裕&#xff0c;也就想了好多事情。首先我想明白的第一件事就是做任何事就要勇敢的去面對、去追求。喜歡一個女孩子大概有8年了吧&#xff01;這期間我們…

8086邏輯移位指令SHL和SHR

SHL邏輯左移指令 SHL OPRD M;把操作數OPRD左移M位,M為位移次數,為1或為CL(位移超過1次用CL表示) ;每移動一位右邊用0補足一位,移出的最高位進入CF(最后移出的一位寫入CF) MOV AL,00010011B ;13H 00010011B SHL AL,1 ;把AL左移1位,移出的最高位0進入CF,右邊0補足1位…

YTU 2903: A--A Repeating Characters

2903: A--A Repeating Characters 時間限制: 1 Sec 內存限制: 128 MB提交: 50 解決: 30題目描述 For this problem,you will write a program that takes a string of characters,S,and creates a new string of characters,T,with each character repeated R times.That is,…

JavaScript 模擬裝飾者模式

/*** 抽象coffee父類&#xff0c;其實可以不用的*/ function Coffee () {} Coffee.prototype.cost function() {throw 實現這個方法; }; /*** 黑咖啡&#xff0c;其實可以不用繼承的&#xff1b;*/ function BlackCoffee () {} // BlackCoffee.prototype new Coffee(); // Bl…

8086算術移位指令SAL和SAR

SAL算術左移指令同邏輯左移指令進行相同動作,機器指令一樣,只是為了方便記憶而提供的兩個助記符 SAR算術右移指令 SAR OPRD,M ;該指令使操作數右移M位,每移動1位左邊的符號保持不變,移出的最低位進入CF mov al,26H ;00100110B 右移1位 00010011B sar al,1 ;26H/2H13H mov a…

const 和readonly

原文:http://www.cnblogs.com/royenhome/archive/2010/05/22/1741592.html 關于 const和readonly修飾符之間的區別,要牽涉到C#中兩種不同的常量類型: 靜態常量(compile-time constants) 和動態常量(runtime constants) 靜態常量是指編譯器在編譯時候會對常量進行解析,并將常量的…