[原創]obj-c編程15[Cocoa執行個體02]:KVC和KVO的實際運用

來源:互聯網
上載者:User

標籤:style   blog   http   color   資料   2014   

原文連結:obj-c編程15[Cocoa執行個體02]:KVC和KVO的實際運用

 

    我們在第16和第17篇中分別介紹了obj-c的KVC與KVO特性,當時舉的例子比較fun,太抽象,貌似和實際不沾邊哦。那麼下面我們就用一個實際中的例子來看看KVC與KVO是如何運用的吧。

    該例中用到了3種新的控制項類型:NSTableView、NSSlider以及簡單的NSTextField類型。按說不能再在Random類裡添加不沾邊的新增功能了,但是為了簡單,我還是把所有東西都放在Random類裡嘍。程式運行時介面如下:

大家可以看到左上方的文本域控制項用來顯示當前音量,因為它和Random類裡的str_volume(或者是str_vol_way2以及str_vol_way3)屬性做了綁定,所以它會即時更新音量變化的數值;而文本域控制項下方的刻度條控制項可以讓使用者更改音量大小(從0 到 100),它和Random類的屬性volume綁定起來,所以改變刻度就會帶來volume屬性值的變化,相當於對volume屬性做寫者操作哦。有童鞋可能不明白文本域是如何隨著刻度條值的變化而變化的,畢竟他們綁定的不是一個屬性啊!

    其實我在這裡用了KVO的概念,不過這裡我用自己監視的是自己的屬性啊:在Random的init方法中設定被觀察者為self,而觀察者也是self,觀察的KeyPath為@"volume",於是乎若刻度條將volume改變(因為它和volume綁定,所以它刻度的改變會導致volume的改變,上面已經說了,會調用volume的寫者方法。),則self,也就是Random的對象自己會收到通知。不過這裡要注意,不能夠直接在通知回調方法中直接寫:str_volume = [新值] ,因為你這樣沒有調用str_volume的寫者方法,你是直接改執行個體變數本身了,這樣文本域不會有變化的:因為文本域控制項也對str_volume做了KVO,而且該KVO只能監視到str_volume被寫者方法改變的情況,你直接改它執行個體變數,自然沒有反應嘍。要解決這個問題,可以有3種方法:

1 將str_volume定義在interface,並聲明屬性,然後在implementation裡做@synthesize str_volume,這樣我們用[self setStr_volume或self.str_volume的方法(執行個體變數str_volume的寫者方法)修改,自然會通知外部監控器。

 

2 手動發送通知,告知屬性被改了,這也是str_vol_way2的方法;

 

3 用屬性的KVC方式修改其值,這也是str_vol_way3的方法啊(注意:str_vol_way3沒有外部介面哦!)。

然後在人語發聲之前用speech的setVolume方法應用當前的音量大小就可以啦,不過注意該方法setVolume的參數是浮點數,取值範圍為0.0 - 1.0,所以我在代碼中要除以100啊!

    再看視窗右上方的列表視圖控制項,也有幾個地方要注意:

1 它是由幾個控制群組成的,滑鼠要多選幾次才能選中裡面的控制項,如果控制項選的不對,可能就找不到要設定屬性嘍:

 

2 其Connections Inspector中要串連2個地方:dataSource和delegate。前者用來做資料來源的代理,後者做其本身動作的代理哦。如果不設定前者則沒有資料來源,就沒東西顯示啊;同理,若不設定後者就無法響應使用者的動作哦。切記切記。這裡再說說代理,代理就是你調用別的類,可是有些事還是你自己最清楚,所以別的類的有些操作還是得返回來問你自己啊。比如列表視圖控制項對於[col,row]位置顯示的內容是不知道的,所以你必須以回調方法的方式告訴它;再者,如果它的當前選中行發生變化了,他也不知道如何處理,所以也要問你,等於是一個當前行改變的事件發生了,Random類必須提供事件處理函數哦。

    最後,NSTableView控制項還是要按老規矩和Random類串連起來啊,就在其Referencing Outlets裡哦;也就是說它和Random一共發生了3種顯式關係(想歪的自覺面壁去)如所示:

    好了,上面把主要的問題都大致說過了,啥也不說鳥,下面的都在代碼裡嘍(在Cocoa執行個體02的代碼基礎上修改而來):

 1 // 2 //  Random.h 3 //  mac_test 4 // 5 //  Created by kinds on 14-7-4. 6 //  Copyright (c) 2014年 kinds. All rights reserved. 7 // 8  9 #import "comm.h"10 #import <Cocoa/Cocoa.h>11 12 @interface Random : NSObject {13     IBOutlet NSTextField *text_field;14     IBOutlet NSTableView *tab_view;15     NSString *str_volume;16 }17 18 @property NSString *str_volume;19 20 -(IBAction)seed:(id)sender;21 -(IBAction)generate:(id)sender;22 23 @end

 

  1 //  2 //  Random.m  3 //  mac_test  4 //  5 //  Created by kinds on 14-7-4.  6 //  Copyright (c) 2014年 kinds. All rights reserved.  7 //  8   9 #import "Random.h" 10  11 @implementation Random{ 12     NSSpeechSynthesizer *speech; 13     NSArray *voices; 14     NSNumber *volume; 15     NSString *str_vol_way2; 16     NSString *str_vol_way3; 17 } 18  19 @synthesize str_volume; 20  21 -(id)init{ 22     self = [super init]; 23     if(self){ 24         speech = [[NSSpeechSynthesizer alloc] initWithVoice:nil]; 25         voices = [NSSpeechSynthesizer availableVoices]; 26         msg(@"%@",voices); 27          28         volume = [NSNumber numberWithInt:0]; 29         str_volume = [NSString stringWithFormat:@"音量:%@",volume]; 30         str_vol_way2 = str_vol_way3 = str_volume; 31         [self addObserver:self forKeyPath:@"volume"  32                   options:NSKeyValueObservingOptionNew context:nil]; 33     } 34     return self; 35 } 36  37 -(void)observeValueForKeyPath:(NSString *)key_path ofObject:(id)obj  38     change:(NSDictionary *)change context:(void *)context{ 39         NSNumber *new_val = [change objectForKey:NSKeyValueChangeNewKey]; 40         msg(@"volume is change to %@",new_val); 41         //str_volume = @"A"; 42         self.str_volume = [NSString stringWithFormat:@"音量:%i",[new_val intValue]]; 43          44         //syn way 2 45         [self willChangeValueForKey:@"str_vol_way2"]; 46         str_vol_way2 = str_volume; 47         [self didChangeValueForKey:@"str_vol_way2"]; 48         //syn way 3 49         [self setValue:str_volume forKey:@"str_vol_way3"]; 50 } 51  52 -(void)set_voice{ 53     int idx = (int)(random() % [voices count]); 54     [speech setVoice:[voices objectAtIndex:(NSUInteger)idx]]; 55 } 56  57 -(IBAction)generate:(id)sender{ 58     int i = (int)(random() % 100000000000) + 1; 59     msg(@"i = %d",i); 60     [text_field setIntValue:i]; 61     [self set_voice]; 62     //[speech setVolume:[volume floatValue]]; 63     [speech startSpeakingString:[NSString stringWithFormat:@"%i",i]]; 64 } 65  66 -(IBAction)seed:(id)sender{ 67     srandom((unsigned)time(NULL)); 68     NSString *str = @"the seed is reseted!"; 69     [text_field setStringValue:str]; 70     [speech startSpeakingString:str]; 71 } 72  73 -(void)awakeFromNib{ 74     NSDate *now = [NSDate date]; 75     [text_field setObjectValue:now]; 76 } 77  78 -(NSInteger)numberOfRowsInTableView:(NSTableView *)tv{ 79     return (NSInteger)[voices count]; 80 } 81  82 -(id)tableView:(NSTableView *)tv objectValueForTableColumn:(NSTableColumn *)col  83 row:(NSInteger)row{ 84     NSString *v = [voices objectAtIndex:row]; 85     return v; 86 } 87  88 -(void)tableViewSelectionDidChange:(NSNotification *)notification{ 89     NSInteger row = [tab_view selectedRow]; 90     if(row == -1) return; 91      92     NSString *str_voice = [voices objectAtIndex:row]; 93     [speech setVoice:str_voice]; 94     [speech setVolume:[volume floatValue]/100]; 95     [speech startSpeakingString:@"test one time!!!測試一下哦!!!"]; 96     msg(@"new voice = %@",str_voice); 97 } 98  99 -(void)dealloc{100     [self removeObserver:self forKeyPath:@"volume"];101 }102 103 104 @end

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.