ストップウォッチクラスをそのまま使い回して、iPhoneアプリケーションに仕上げます。
前回作ったMac OS Xアプリで、Stopwatchクラスを使っていましたが、
これをそのまま再利用して、iPhoneアプリを作ってみましょう。
Xcodeを起動し、⌘-shift-N(新規プロジェクト...)から、iPhone OSのView-Based Applicationを選んでください。

プロジェクト名は、LogWatch-iPhoneにしましょう。

Finder上で、前回作ったプロジェクトのフォルダ(LogWatch)の中の2つのファイル、Stopwatch.hとStopwatch.mを、

このように、Xcode上のClassesフォルダへドラッグ&ドロップしてください。すると、

こんなシートが出るのでターゲット(LogWatch-iPhone)を確認して、追加。

Finderで確認すると、このように

2つのファイルがコピーされました。
そしてオブジェクトの関係図を書いてみます。
黒で書いたところはこのプロジェクト(View-Based Application)が最初に用意してくれた部分で、
赤で書いたところが、今回自前で設置する部分です。
NIBファイル(拡張子が.xib)は2つ用意されてあって、そのうちLogWatch_iPhoneViewController.xibのほうを編集します。
そのファイルをダブルクリックしてインターフェースビルダーを起動させ、
テキストビュー(UITextView)、ラベル(UILabel)、ボタン2つ(UIButton)、それからUIActivityIndicatorViewを次のように配置しましょう。

GUIが見えてくると俄然もりあがってきますねー。

Activity Indicator View (UIActivityIndicatorView)の設定で、Hide When Stoppedをオンにします。
さてXcodeにもどって、ビューコントローラーのヘッダファイル(LogWatch_iPhoneViewController.h)を、次のようにします。
#import <UIKit/UIKit.h>
@class Stopwatch;
@interface LogWatch_iPhoneViewController : UIViewController {
IBOutlet UILabel *timeDisplay;
IBOutlet UIButton *startStopButton, *resetButton;
IBOutlet UIActivityIndicatorView *busyIndicator;
IBOutlet UITextView *logView;
Stopwatch *watch;
NSTimer *timer;
NSMutableArray *log;
}
- (IBAction)pushStartStop:(id)sender;
- (IBAction)pushReset:(id)sender;
- (void)updateUI:(NSTimer *)t;
@end
さっき示したオブジェクトの関係図のどこに対応するか、確認してみてください。
そしてビューコントローラーの実装ファイル(LogWatch_iPhoneViewController.m)を以下のように。
#import "LogWatch_iPhoneViewController.h"
#import "Stopwatch.h"
@implementation LogWatch_iPhoneViewController
- (void)updateUI:(NSTimer *)t
{
NSTimeInterval second = watch.second;
NSString *s = [[NSString alloc] initWithFormat:@"%.2f", second];
timeDisplay.text = s;
[s release];
}
- (IBAction)pushStartStop:(id)sender
{
[watch startStop];
if (watch.isBusy) {
// START
timer = [NSTimer scheduledTimerWithTimeInterval:0.01
target:self
selector:@selector(updateUI:)
userInfo:nil
repeats:YES];
[timer retain];
[startStopButton setTitle:@"STOP" forState:UIControlStateNormal];
resetButton.userInteractionEnabled = NO;
resetButton.alpha = 0.5;
[busyIndicator startAnimating];
}
else {
// STOP
[timer invalidate];
[timer release];
[startStopButton setTitle:@"START" forState:UIControlStateNormal];
resetButton.userInteractionEnabled = YES;
resetButton.alpha = 1.0;
[busyIndicator stopAnimating];
// Log
[log addObject:timeDisplay.text];
NSString *s = [log componentsJoinedByString:@"\n"];
logView.text = s;
NSRange logEnd;
logEnd.location = [s length] - 1;
[logView scrollRangeToVisible:logEnd];
}
}
- (IBAction)pushReset:(id)sender
{
if (watch.isBusy)
return;
[watch reset];
[self updateUI:nil];
}
- (void)viewDidLoad {
[super viewDidLoad];
watch = [[Stopwatch alloc] init];
log = [[NSMutableArray alloc] init];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)dealloc {
[watch release];
[log release];
[super dealloc];
}
@end
前回作ったAppControllerと似たところが多いです。
最後にインターフェースビルダーでビューコントローラーと各オブジェクトを接続します。
今編集中のnibファイルのFile's Ownerは
ビューコントローラーがおさまっています。
ビューコントローラーのアウトレットとアクションを、接続していってください。

全部つなぐと、このようになります。
説明なしでやっちゃってる部分がたくさんあるのですが・・・
とても解説しきれません・・・申し訳ない・・・
今回の目玉は、Mac OS Xアプリ上で設計したオリジナルのクラスを、
まったく変更することなしに、iPhoneアプリで使い回す例でございました。
将来、アプリケーション開発で時間を計測する必要が生じたときに、
Stopwatchクラスをさくっと利用すれば、ぐっと効率があがってハッピーになるかもしれません。
