Cocoa プログラミング概観

ID: 11
creation date: 2010/04/08 01:20
modification date: 2010/04/09 22:16
owner: taiji
tags: Cocoa, Mac OS X, Objective-C
image:1:Do6HkZkVlqQAAAAASUVORK5CYII=
image:2:AAAAAElFTkSuQmCC

コードなしで動かしてみる - Outlets, Target/Action 体験

  1. Shift+Command+N で新規プロジェクト、Core Data Application、プロジェクト名を「SpeechClock」として「完了」。
  2. SpeechClock プロジェクトで「MainMenu.nib」をダブルクリックしてインターフェースビルダー(IB)で開く。
  3. Instances の「Window」を delete。かわりに、Cocoa Windows の「NSWindow and NSDrawer」を Instances へ。すると、NSDrawer1 と Parent Window と DrawContentView というインスタンスが作られる。
  4. Parent Window のタイトルを Command+1 で「SpeechClock」に変更。
  5. Cocoa Controls の NSButton を「SpeechClock」Window へ。NSButton のタイトルは「Voice」とする。Command+1 で「Visible at launch time」をオンにしておく。
  6. Voice ボタンから Control を押しながら「NSDrawer1」へ「toggle:」Action で Connect。
  7. ウィンドウが狭いと作り難いので、とりあえずサイズを 480x360 ぐらいに広くしておこう。
  8. 「NSDrawer1」の Preferred Edge を Command+1 で「Bottom」にしておく。
  9. ここで、IB 上で、Command+R で試験。Voice ボタンで NSDrawer ウィンドウが出現すれば成功。

データのためのテーブルを配置してみる - Core Data とレイアウトの体験

  1. SpeechClock プロジェクトで「SpeechClock_DataModel.xcdatamodel」を開き、エンティティ「voices」(クラスは規定の NSManagedObject)を作成。属性は「voice、文字列」とする。
  2. 次の操作に備え、MainMenu.nib を IB で開いておく。
  3. voices エンティティを Option を押しながら、「DrawContentView」Windowへ。さまざまな Cocoa Controls が生成される。
  4. 生成された NSTableView について「Use Alternating Raw Background」「Automatically Hide Scrollers」を有効にした。
  5. 生成されたさまざまな部品の配置はなるべくコンパクトにまとめ、NSDrawer1 の Command+3 のサイズで最小/最大サイズ等を調整するとよい。
  6. それぞれの部品の自動サイズを調整し、意図するレイアウトになるまで Command+R で試しながら調整するとよい。

コードを書いて動かしてみる - Outlet の作成と Connection を体験

  1. SpeechClock プロジェクトで「SpeechClock_AppDelegate.h」と「SpeechClock_AppDelegate.m」をリスト1のように編集する。
  2. Classes の「SpeechClock_AppDelegate」(インスタンスをダブルクリックするとクラスへ)の Command+1 で outlet として「sampleTextField」、action として「startSpeechSampleText」と「stopSpeechSampleText」を追加する。
  3. NSBox を「DrawContentView」Windowへ。タイトルは「Speech」とする。さらに、NSTextField と2つの NSButton を「Speech」Box へ。NSTextField のタイトルは適当なゼリフ「Well begun is half done.」、NSButton のタイトルは配置の右から「Speak」「Stop」とする。
  4. speech「Speak」Button から SpeechClock_AppDelegate の「startSpeechSampleText」へ Connection。
  5. speech「Stop」Button から SpeechClock_AppDelegate の「stopSpeechSampleText」へ Connection。
  6. SpeechClock_AppDelegate の「sampleTextField」outlet から speech NSTextField へ Connection。
  7. ここで、Xcode上で、Command+R で試験。Speak ボタンを押して声がして、Stop ボタンで途中で止められれば成功。

リスト1

--- SpeechClock_AppDelegate.h~01	2010-04-09 12:49:38.000000000 +0900
+++ SpeechClock_AppDelegate.h	2010-04-09 14:58:15.000000000 +0900
@@ -11,6 +11,8 @@
 @interface SpeechClock_AppDelegate : NSObject 
 {
     IBOutlet NSWindow *window;
+    IBOutlet NSTextField *sampleTextField;
+    NSSpeechSynthesizer *speechSynthesizer;
     
     NSPersistentStoreCoordinator *persistentStoreCoordinator;
     NSManagedObjectModel *managedObjectModel;
@@ -23,4 +25,7 @@
 
 - (IBAction)saveAction:sender;
 
+- (IBAction)startSpeechSampleText:(id)sender;
+- (IBAction)stopSpeechSampleText:(id)sender;
+
 @end
--- SpeechClock_AppDelegate.m~01	2010-04-09 12:49:38.000000000 +0900
+++ SpeechClock_AppDelegate.m	2010-04-09 14:59:18.000000000 +0900
@@ -10,6 +10,23 @@
 
 @implementation SpeechClock_AppDelegate
 
+- (id)init
+{
+  [super init];
+  speechSynthesizer = [[NSSpeechSynthesizer alloc] initWithVoice:nil];
+  return self;
+}
+- (IBAction)startSpeechSampleText:(id)sender
+{
+  NSString *string;
+  if (![(string = [sampleTextField stringValue]) length])
+    return;
+  [speechSynthesizer startSpeakingString:string];
+}
+- (IBAction)stopSpeechSampleText:(id)sender
+{
+  [speechSynthesizer stopSpeaking];
+}

部品の状態を制御する - delegate Outlet の作成、awakeFromNib の利用を体験

  1. 「SpeechClock_AppDelegate.h」と「SpeechClock_AppDelegate.m」をリスト2のように編集する。
  2. Classes の「SpeechClock_AppDelegate」の Command+1 で outlet として「startSpeechSampleTextButton」と「stopSpeechSampleTextButton」を追加する。
  3. SpeechClock_AppDelegate の「startSpeechTextField」outlet から「Speak」Button へConnection。
  4. SpeechClock_AppDelegate の「stopSpeechTextField」outlet から「Stop」Button へConnection。
  5. ここで、Xcode上で、Command+R で試験。起動時に Stop ボタンは無効化されていて、Speak ボタンを押して声がしている間は「Speak」Button が無効化され、声が終われば元に戻れば成功。

リスト2

--- SpeechClock_AppDelegate.h~02	2010-04-09 14:58:15.000000000 +0900
+++ SpeechClock_AppDelegate.h	2010-04-09 15:10:10.000000000 +0900
@@ -13,6 +13,8 @@
     IBOutlet NSWindow *window;
     IBOutlet NSTextField *sampleTextField;
     NSSpeechSynthesizer *speechSynthesizer;
+    IBOutlet NSButton *startSpeechSampleTextButton;
+    IBOutlet NSButton *stopSpeechSampleTextButton; 
     
     NSPersistentStoreCoordinator *persistentStoreCoordinator;
     NSManagedObjectModel *managedObjectModel;
--- SpeechClock_AppDelegate.m~02	2010-04-09 14:59:18.000000000 +0900
+++ SpeechClock_AppDelegate.m	2010-04-09 15:16:44.000000000 +0900
@@ -14,20 +14,35 @@
 {
   [super init];
   speechSynthesizer = [[NSSpeechSynthesizer alloc] initWithVoice:nil];
+  [speechSynthesizer setDelegate:self];
   return self;
 }
+- (void)awakeFromNib
+{
+  [startSpeechSampleTextButton setEnabled:!NO];
+  [stopSpeechSampleTextButton setEnabled:!YES];
+}
 - (IBAction)startSpeechSampleText:(id)sender
 {
   NSString *string;
   if (![(string = [sampleTextField stringValue]) length])
     return;
   [speechSynthesizer startSpeakingString:string];
+  [startSpeechSampleTextButton setEnabled:NO];
+  [stopSpeechSampleTextButton setEnabled:YES];
 }
 - (IBAction)stopSpeechSampleText:(id)sender
 {
   [speechSynthesizer stopSpeaking];
 }
 
+- (void)speechSynthesizer:(NSSpeechSynthesizer *)sender
+	didFinishSpeaking:(BOOL)success
+{
+  [startSpeechSampleTextButton setEnabled:!NO];
+  [stopSpeechSampleTextButton setEnabled:!YES];
+}
+

データの状態を取得する - NSArrayController の利用を体験

  1. 「SpeechClock_AppDelegate.h」と「SpeechClock_AppDelegate.m」をリスト3のように編集する。
  2. Classes の「SpeechClock_AppDelegate」の Command+1 で outlet として「arrayController」を追加する。
  3. SpeechClock_AppDelegate の「arrayController」outlet から「Voices Array Controller」へConnection。
  4. ここで、Xcode上で、Command+R で試験。NSTableView に例えば「com.apple.speech.synthesis.voice.Agnes」などを入力してみて、声色が変更できれば成功。
  5. さらに、正常終了させた後、改めて実行した時に、前に入力したデータが保存されていれば成功。

リスト3

--- SpeechClock_AppDelegate.h~03	2010-04-09 15:10:10.000000000 +0900
+++ SpeechClock_AppDelegate.h	2010-04-09 15:30:33.000000000 +0900
@@ -15,6 +15,7 @@
     NSSpeechSynthesizer *speechSynthesizer;
     IBOutlet NSButton *startSpeechSampleTextButton;
     IBOutlet NSButton *stopSpeechSampleTextButton; 
+    IBOutlet NSArrayController *voicesArrayController;
     
     NSPersistentStoreCoordinator *persistentStoreCoordinator;
     NSManagedObjectModel *managedObjectModel;
--- SpeechClock_AppDelegate.m~03	2010-04-09 15:16:44.000000000 +0900
+++ SpeechClock_AppDelegate.m	2010-04-09 15:32:56.000000000 +0900
@@ -27,6 +27,10 @@
   NSString *string;
   if (![(string = [sampleTextField stringValue]) length])
     return;
+  NSString *voice = ([[voicesArrayController selectionIndexes] count] == 1) ?
+    [voicesArrayController valueForKeyPath:@"selection.voice"] :
+    [NSSpeechSynthesizer defaultVoice];
+  [speechSynthesizer setVoice:voice];
   [speechSynthesizer startSpeakingString:string];
   [startSpeechSampleTextButton setEnabled:NO];
   [stopSpeechSampleTextButton setEnabled:YES];

データの状態を制御する - NSManagedObject の利用を体験

  1. 「SpeechClock_AppDelegate.h」と「SpeechClock_AppDelegate.m」をリスト4のように編集する。
  2. NSButton を「Speech」Box へ1つ追加。NSButton のタイトルは「default」とする。
  3. Classes の「SpeechClock_AppDelegate」の Command+1 で action として「setVoicesByDefault」を追加する。
  4. speech「default」Button から SpeechClock_AppDelegate の「setVoicesByDefault」へ Connection。
  5. ここで、Xcode上で、Command+R で試験。default ボタンでシステム標準の声色リストが NSTableView に揃えられ、選択した声色に変更できれば成功。
  6. さらに、正常終了させた後、改めて実行した時に、前に入力したデータが保存されていれば成功。

リスト4

--- SpeechClock_AppDelegate.h~04	2010-04-09 15:30:33.000000000 +0900
+++ SpeechClock_AppDelegate.h	2010-04-09 16:03:43.000000000 +0900
@@ -30,5 +30,6 @@
 
 - (IBAction)startSpeechSampleText:(id)sender;
 - (IBAction)stopSpeechSampleText:(id)sender;
+- (IBAction)setVoicesByDefault:(id)sender;
 
 @end
--- SpeechClock_AppDelegate.m~04	2010-04-09 15:32:56.000000000 +0900
+++ SpeechClock_AppDelegate.m	2010-04-09 16:40:41.000000000 +0900
@@ -39,6 +39,22 @@
 {
   [speechSynthesizer stopSpeaking];
 }
+- (IBAction)setVoicesByDefault:(id)sender
+{
+  NSArray *voices = [NSSpeechSynthesizer availableVoices];
+  int i;
+  //[voicesArrayController willChangeValueForKey:@"voice"];	// unnecessary
+  [voicesArrayController setFilterPredicate:nil];
+  [voicesArrayController removeObjects:[voicesArrayController arrangedObjects]];
+  for (i=0; i<[voices count]; i++) {
+    NSManagedObject *voice =
+      [NSEntityDescription insertNewObjectForEntityForName:@"voices"
+			   inManagedObjectContext:[self managedObjectContext]];
+    [voice setValue:[voices objectAtIndex:i] forKey:@"voice"];
+    [voicesArrayController addObject:voice];
+  }
+  //[voicesArrayController didChangeValueForKey:@"voice"];	// unnecessary
+}
 
 - (void)speechSynthesizer:(NSSpeechSynthesizer *)sender
 	didFinishSpeaking:(BOOL)success

時計を表示 - キーバリューコーディング(KVC)とバインド、NSTimerとセレクタを体験

  1. 「SpeechClock_AppDelegate.h」と「SpeechClock_AppDelegate.m」をリスト5のように編集する。
  2. NSBox を Parent Window である「SpeechClock」Windowへ。タイトルは「Clock」とする。さらに、NSTextField を「Clock」Box へ。NSTextField のタイトルは「clock」とする。
  3. clock TextField の value バインドを Command+4 で「SpeechClock_AppDelegate、Controller Key はなし、Model Key Path は currentDate」とする。
  4. ここで、Xcode上で、Command+R で試験。clock TextField が時計として動いていれば成功。

リスト5

--- SpeechClock_AppDelegate.h~05	2010-04-09 16:03:43.000000000 +0900
+++ SpeechClock_AppDelegate.h	2010-04-09 21:55:22.000000000 +0900
@@ -16,6 +16,8 @@
     IBOutlet NSButton *startSpeechSampleTextButton;
     IBOutlet NSButton *stopSpeechSampleTextButton;
     IBOutlet NSArrayController *voicesArrayController;
+    NSDate *currentDate;
+    NSTimer *clockTimer;
     
     NSPersistentStoreCoordinator *persistentStoreCoordinator;
     NSManagedObjectModel *managedObjectModel;
@@ -32,4 +34,12 @@
 - (IBAction)stopSpeechSampleText:(id)sender;
 - (IBAction)setVoicesByDefault:(id)sender;
 
+#if !defined(MAC_OS_X_VERSION_10_5) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
+- (NSDate *)currentDate;
+- (void)setCurrentDate:(NSDate *)aCurrentDate;
+#else
+@property(readwrite, retain) NSDate *currentDate;
+#endif
+- (void)updateCurrentDate;
+
 @end
--- SpeechClock_AppDelegate.m~05	2010-04-09 16:40:41.000000000 +0900
+++ SpeechClock_AppDelegate.m	2010-04-09 21:56:09.000000000 +0900
@@ -15,12 +15,18 @@
   [super init];
   speechSynthesizer = [[NSSpeechSynthesizer alloc] initWithVoice:nil];
   [speechSynthesizer setDelegate:self];
+  currentDate = [[NSDate alloc] init];
   return self;
 }
 - (void)awakeFromNib
 {
   [startSpeechSampleTextButton setEnabled:!NO];
   [stopSpeechSampleTextButton setEnabled:!YES];
+  clockTimer = [[NSTimer scheduledTimerWithTimeInterval:1
+			 target:self
+			 selector:@selector(updateCurrentDate)
+			 userInfo:nil
+			 repeats:YES] retain];
 }
 - (IBAction)startSpeechSampleText:(id)sender
 {
@@ -56,6 +62,28 @@
   //[voicesArrayController didChangeValueForKey:@"voice"];	// unnecessary
 }
 
+#if !defined(MAC_OS_X_VERSION_10_5) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
+- (NSDate *)currentDate
+{
+  return currentDate;
+}
+- (void)setCurrentDate:(NSDate *)aCurrentDate
+{
+  [aCurrentDate retain];
+  [currentDate release];
+  currentDate = aCurrentDate;
+}
+#else
+@synthesize currentDate;
+#endif
+
+- (void)updateCurrentDate
+{
+  //[self willChangeValueForKey:@"currentDate"];	// unnecessary
+  [self setCurrentDate:[[NSDate alloc] init]];
+  //[self didChangeValueForKey:@"currentDate"];	// unnecessary
+}
+
 - (void)speechSynthesizer:(NSSpeechSynthesizer *)sender
 	didFinishSpeaking:(BOOL)success
 {
----
0 コメント
ゲストコメント認証用なぞなぞ:
キーボードのLから左に全部打って下さい。それを二回やって下さい。 ...