2008年11月26日水曜日

CS193P Cocoa Programming - 6日目おまけ、多角形をくるくる回せるようにしてみた

  • CS193P(http://www.stanford.edu/class/cs193p/cgi-bin/index.php)のチュートリアルで作っているHelloPolyプロジェクトを自分なりにアレンジしてみた
  • 自分なりにアレンジしてみた=ニコニコ動画だと駄作フラグ
  • UIViewはhiddenプロパティをYESにした瞬間に消えてしまうので、アニメーションでフェードアウトさせたいときは、まずアニメーションだけ実行>アニメーション終了時のデリゲータ(- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag)で実際にUIViewをhiddenにする
  • タッチ動作を取得するには、UIView(正確にはUIResponder)のtouchBeganメソッドやtouchMovedメソッドをオーバーライドする
  • デフォルトではマルチタッチ不可能(最初の1タッチのみ感知する)、マルチタッチしたければ設定を変えること
  • UITouch.tapCountでタップした数を取得できる。これを使ってダブルタップを検出できるが、連打すると3とか4とか2より大きい数が取得されてしまうので注意
  • CGPointはクラスではなくて構造体、頭にCGがつくCore Graphics系はすべて純粋C言語であるところに注意!
  • CGPointなどを作成するときはCGPointMake()関数を使う
  • CGPointやCGRectなどをObjective-Cのクラスとして扱いたいときはNSValueクラスを使う、たとえば[NSValue valueWithCGPoint:(CGPoint)point]など
  • CGRectGetMidX()関数とか地味に超便利
  • C言語の変数の有効範囲について:http://www.cis1.c.dendai.ac.jp/c_master/C_14.htm
    CGPointMake()で作ったCGPointなどは自動変数なので、別のメソッドに渡すときはポインタ渡しではなくてそのまま値で渡す

ただ単にカリキュラムにそって進めていくだけでは面白くないので、この辺りでちょっとチャレンジングなことをしてみることにしました


まずは新しくサブビューを追加。


ON OFFスイッチでビューを出したり消したり。出したり消したりするときはアニメーションします。


UISliderを使って、線の太さを変えてみましたよ。
UISliderのvalueプロパティはdouble型なので注意です。ずっとNSString型だと思ってました。
それから、タップした向きに多角形を回転できるようにしました。赤線は中心からタップした点への線分です。
タップしてドラッグするとスムー(?)ズに回転しますよ。


破線への切り替えもできるようにしました。
UISegmentedControlを使っています。このUISegmentedControl、取得できる値が選択されているセグメントのインデックス番号(selectedSegmentIndex)だけなのでちょっと厄介です。HTMLのラジオボタンみたいに好きな値をセグメントごとに持たせられればいいのに。


今回作成したアプリのプロジェクトファイルを公開してみました。
面白いことをやっている点は何一つないのですが、まぁ一応。
http://sites.google.com/site/akisutesama/files/HelloPoly-06b.zip?attredirects=0

今後はgithubとかで公開できるようにします。

2008年11月22日土曜日

CS193P - ここまでの進捗をアップしてみた

ここまでのCS193Pの進捗をアップしてみました。

http://sites.google.com/site/akisutesama/files/HelloPoly-06.zip?attredirects=0

Xcode3.1用のプロジェクトファイルと、ソース一式が入っています。
Max OS Xで解凍してXcodeで読み込んでコンパイルできると思います。たいした内容ではありませんが一応。

CS193P Cocoa Programming - 6日目、NSUserDefaultsの使い方

  • アプリケーションが終了した後もデータを保持したい(例:現在開いているページなど)
  • NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  • あとはNSDictionaryとほとんど同じ(格納の仕方も取得の仕方も)
  • BOOLとかintをそのまま格納できるメソッドもあります
  • 格納するタイミングは、値がかわった瞬間かまたはアプリが終了する瞬間
  • 取得するタイミングは、アプリが立ち上がった瞬間かまたはawakeFromNibメソッド
今日はNSUserDefaultsとやらの使い方を学習。
NSUserDefaultsとはアプリケーションが終了した後もデータを保持することができる仕組みのようです。
本格的にデータを保存したいならSQLiteやファイルを使うんでしょうが、ちょっとしたデータ(例えば現在開いているページ)を保持したいときなどにSQLを書くのは煩雑です。そういうときに便利に使える仕組みらしいです。

○値を格納する
タイミングは二つ。値がかわった瞬間か・・・
//ボタン押し下げ時に値を減らす
- (IBAction)decrease {
int currentNum = polygonShape.numberOfSides;
currentNum--;
polygonShape.numberOfSides = currentNum;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setInteger:currentNum forKey:@"numberOfSides"];
[self updateInterface];
}
またはアプリケーションが終了するタイミングか。
//@implementation HelloPolyAppDelegate(アプリケーションのデリゲートの中で)
- (void)applicationWillTerminate:(UIApplication *)application {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setInteger:controller.model.intValue forKey:@"numberOfSides"];
}
パフォーマンスに応じてどちらか好きな方を選んでくださいとのことです。

○値を取得する
こちらもタイミングは二つ。アプリケーションが立ち上がったタイミングか・・・
//@implementation HelloPolyAppDelegate(アプリケーションのデリゲートの中で)
- (void)applicationDidFinishLaunching:(UIApplication *)application {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
int storedNumberOfSides = [defaults integerForKey:@"numberOfSides"];
controller.model.intValue = storedNumberOfSides;
[window makeKeyAndVisible];
}

または対象のクラスのawakeFromNibメソッドの中か。
//ここではコントローラクラスの中で・・・
- (void)awakeFromNib {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
int storedNumberOfSides = [defaults integerForKey:@"numberOfSides"];
self.model.intValue = storedNumberOfSides;
[self updateInterface];
}

この二つの違いは正直わかってません。複数のNibファイルを利用するときはawakeFromNibでないと駄目らしいですが・・・