LV1

駆け出し三十路プログラマー奮闘記。iPhone/Macを中心に絶賛修行中。

iOSでのオブザーバーパターンを実現するには

ViewControllerの肥大化を解消すべく奮闘中です。
複数のViewに値の変更を通知したいのですけど、iOSで用意されている機能では、

  • NSNotificationCenter
  • KVO(KeyValueObserving)

の3つが使えると。

KVOは、昔InterfaceBuilderで値とUIの同期設定ができる便利機能くらいにしか捉えてなくて忘れかけてました;;
Delegateは通知相手が一人向きですし、今回のように複数のViewに通知したいといったケースではKVOが活躍してくれそうな予感。再び試してみますよ!

1枚のUIImageViewで画像をクロスフェードする

CATransitionを使うことで1枚のUIImageViewだけでも画像のクロスフェードが実現できました。

void crossfade(UIImageView* view, NSString* imageName)
{
     CATransition* transition = [CATransition animation];
     transition.duration = 2.0f;
     transition.type = kCATransitionFade;
    
     [view.layer addAnimation:transition forKey:nil];
    
     UIImage* image = [UIImage imageNamed:imageName];
     view.image = image;
}

もともとは、

[UIView animateWithDuration:animations:]

を試したんですが、このアニメーションブロックの中でview.imageを変更してもアニメーションされませんでした。この場合は、2枚のUIImageViewを用意してアルファ値を変更する等のアプローチが必要になりそうです。

Macでフォルダを新規ウィンドウで開くキーボードショートカット

「コマンド+コントロール+O」です!

これ、ずっと探していたんですー!

カラム表示で使っていると、一時的にフォルダを別ウィンドウで開きたい時があるんですよー。「コマンド+マウスダブルクリック」でも可能ですが、やっぱりキーボードだけでできるとラクチンです!

ちなみに、私はTotalFinderを入れているので新規タブが開きます。

Mac OS X 10.6.8 Snow Leopard で確認しました。

順番に実行したい処理をマルチスレッドで直感的に書く

ここのところ、ネットワークの非同期通信を使うためにマルチスレッドプログラミングと格闘していました。

そんな中、ふと「これって、RPGのバトルみたいに、○○の攻撃!→××の攻撃!みたいに順番に処理したいゲームプログラミングで使えるんじゃない!?」と思いサンプルを書いてみました。

マルチスレッドにはiOS4で導入されたGCDを使っています。

- (void)mainLoop:(NSTimer*)timer //NSTimerから定期的に呼ばれる
{
	if (!_hasStarted) {
		//以下のブロックをスレッドで処理
		dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
			[self msg:@"spkrlnのこうげき"];
			[self wait:3.0];
			[self msg:@"いっかくうなぎに30のダメージ!!"];
			[self wait:3.0];
		});
		_hasStarted = YES;
	}
	//描画はメインスレッドから毎フレーム呼ばれる
	[self draw];
}

- (void)msg:(NSString*)message
{
	for (int i = 1; i <= [message length]; ++i) {
		NSString* substr = [message substringToIndex:i];
		//UIの更新はメインスレッドで!
		dispatch_async(dispatch_get_main_queue(), ^{
			[_textView setText:substr];
		});
		//メソッドから抜けることなくスリープで済ませられちゃう!
		[NSThread sleepForTimeInterval:0.05];
	}
}

- (void)wait:(NSTimeInterval)seconds
{
	//ここもスリープでおk!
	[NSThread sleepForTimeInterval:seconds];
}

特に、

[self msg:@"spkrlnのこうげき"];
[self wait:3.0];
[self msg:@"いっかくうなぎに30のダメージ!!"];
[self wait:3.0];

の部分など、普通なら文字送りやウェイトのせいで、1回のメソッド呼び出しで処理が完了することはないので、いったん状態を変数に保存してメソッドを抜けて、次のフレームで条件分岐して処理を引き継いで…と、なかなかきれいに書けないのですが、今回はとても直感的に書けました。
Luaのコルーチンのような感じ。これはいいかも。

NSLogでポインタのアドレスを出力する

NSLogでポインタのアドレスを出力する書式があるのを知りました。

NSObject* obj = [[NSObject alloc] init];
NSLog(@"%p", obj);

これで「0x681d640」などと、頭に0xをつけて16進数で出力してくれます。
今までは

NSLog(@"%08X", (int)obj);

などとやっていましたが、%pの方が断然シンプルですね!
※調べてみたら、既にprintfでも%pに対応していたようです。

ARC オンの時のretain count の確認方法

auto reference counting(ARC)がオンだと"retainCount"メソッドが使えませんが、Core Foundationの関数で代用できるようです。

NSObject* obj = [[NSObject alloc] init];
NSLog(@"%d", (int)CFGetRetainCount((__bridge CFTypeRef)obj));

ARC管理下のオブジェクトをそうでない型にキャストするために__bridgeキャストしています。

Redmineをシンプルな手順で公開できるOpenShift

ワンクリックでRedmineをセットアップでき無料で使えるPaaS、fluxflexが今月末で閉鎖するとアナウンスされた。

 

それに代わるサービスがないか探してみたところ

heroku

OpenShift

が候補に。

 

herokuはrubyの作法の理解が必要、かつフォルダの運用方法にクセがあり、1日格闘した末に挫折。

 

そこでRedHatのOpenShift。デベロッパープレビュー版が無償で使える。

GitHubにOpenShift用Redmine一式が公開されていて、データベースの設定ファイルを書き換えてアップするだけで動いてしまう。

データベースの管理にPhpMyAdminが使えるのもうれしい。

 

まずはOpenShiftでのアプリケーションの作成方法。

英語だけど丁寧なチュートリアル。

 

https://openshift.redhat.com/app/getting_started

 

そしてRedmineのセットアップ手順。

 

https://openshift.redhat.com/community/blogs/phpmyadmin-your-way-into-openshift-express-database-management-bliss

 

ここに書いてあるrhc〜のコマンド名は古いかも?私は最新ドキュメントのコマンド名に読みかえた。あとrhc app createのオプションはrackではなくruby-1.8を指定してみた。

 

ハマったこと。

上記リンクの説明は、コマンドラインでアプリケーションを作ることを前提にしているため、ブラウザの管理画面でアプリケーションを作ったり、クイックスタートのGitHubからgit cloneした場合、チュートリアル通りにいかなくなる。

チュートリアル通りにやるなら、コマンドラインでを作った方が混乱が無いと思う。

 

今回はRedmineをセットアップしたけど、phpも使えるし、WordPressなどブラウザの管理画面から作成できるアプリも色々あるみたい。

今度はぜひ自作のwebアプリを公開してみたい。