アーカイブ

2009 年 12 月 のアーカイブ

超高解像度イラストアプリ:pixlovシリーズの販売開始

2009 年 12 月 25 日 akiraak コメントはありません

超高解像度イラストアプリ、pixlovシリーズの販売を開始しました。非劣化画像フォーマットであるPNGを使用し、1000x2000以上の高い解像度で、書籍・コミケ・個展などで活躍するイラストレーターの絵をお楽しみいただけます。

合わせて、世界中の人がpixlovアプリ内から付けたお気に入りハートをWEBから確認できるpixlovウェブサイトも開始しました。


イラストレーター・クラムゼリー氏による [pixlov] Drawnica-Drawnica vol.1

[pixlov] Creatures vol.1

screenshot_01screenshot_03screenshot_05

pixlovサイトはこちら

■アプリ紹介

コミケで活躍中のモンスター絵師、木喬 (hashi) の描くイラストがアプリケーションになりました。躍動感あふれる幻獣たちをご覧ください。

- オフィシャルホームページ Or2
- イラスト誌 CanVas
- イラスト誌 LOVES

[pixlov] Look, it’s me vol.1

screenshot_01screenshot_02screenshot_04

pixlovサイトはこちら

■アプリ紹介

自閉症(発達障害、アスペルガー症候群)を持つ画家、森豊和が描いた作品を集めました。

彼は何かとつながることで「寂しさをなくしたい」と思っています。

絵を描くことで彼は自身の世界とつながります。そして、絵をみてもらうことで彼は他の人の世界、現実の世界とつなります。

この作品で新たなつながりが生まれることを彼は願っています。

カテゴリー: 発売 タグ:

iPhoneアプリで半自動の画面回転インターフェイス

2009 年 12 月 11 日 akiraak コメントはありません

iPhone の Safari などを使っていて、自分が意図していないのに画面が横向きに変わったりしてイライラする事はないでしょうか?私は何度もあります。自分が iPhone を微妙に傾けてしまうのが原因ですが、これを解決しようと思い動画のようなインターフェイスを作成しました。

傾きを感知すると回転用のボタンが表示され、それをタッチすると画面が回転。ボタン以外をタッチすると回転ボタンが消えます。また、今回はまだ実装していませんが、ボタンが表示され2秒ほど経過するとボタンが自動で消えるようにしようと思います。

カテゴリー: 開発 タグ:

「屋久島 写真と地図で見る精霊の森」発売

2009 年 12 月 10 日 akiraak コメントはありません

phf1_icon_reflection_96x100

「屋久島 写真と地図で見る精霊の森」の発売を開始しました。

■アプリケーションの説明

屋久島は、1993年 ユネスコの世界自然遺産に登録された、日本を代表する、自然豊かな美しい島です。(白神山地とともに日本初の自然遺産登録となりました。)

その安らぎの島の魅力を、15年前から、鹿児島、沖縄の島々を尋ね歩く映像作家K-bimヒロが、写真に収めました。

屋久島は、「月に35日雨が降る」と喩えられるほどの雨量があり、それによって、広範囲に苔で覆われた、癒しの森を育みました。宮崎駿監督の映画「もののけ姫」の舞台設定にも使われた、”白谷雲水峡”を中心に、森に満ちた息吹、”精霊の気配”をテーマに撮影した写真集となっています。

今にも動き出しそうな、躍動感あるダイナミックな森と、その足元や木々の表面に広がる、清浄な水を蓄えた苔の森。マクロとミクロの二つの森が、訪れる人たちを優しく迎え、日本の自然美を私達に伝えてくれます。

時には日常の慌しさから離れ、iPhoneを手に,癒しの森を散歩してみては如何でしょうか。

写真集としての楽しみのほか、撮影地点がマップにリンクしていますので、観光ガイドとしてもお使いいただけます。(表示される場所は、厳密な撮影地点とは限りません、)

■収録点数

横位置作品 36点 縦位置作品 34点 計70点

■主な機能

時計機能(表示のON OFF可)
撮影場所の表示(表示のON OFF可)
BGM の再生(再生のON OFF可)
スライドショー(再生時間を自由に設定できます)
ランダム表示
オートリピート
縦向き・横向き表示対応
収録写真の保存(保存先から壁紙設定可能)
快適なフリック操作
Google マップを表示

■操作方法

「画面タップ」でインフォメーション画面及び「地図」「保存」が表示されます
「画面上部をタップ」でメニューが表示されます
「手動モード」時に「画面下部をタップ」でサムネイルが表示されます
「手動モード」時に「画面端をタップ」で写真が変わります
「本体の向きを変える」ことにより写真の縦横を切り替えます

■注意点

Googleマップへの表示はインターネットに接続された環境でないと表示されません。
アプリ内での快適なマップ表示機能はOS3.0以上が必要です。OS3.0未満の場合はマップアプリが起動して位置が表示されます。
音量の調整は本体のボタンで行ってください。

■条件

iPhone 及び iPod touch 互換
iPhone OS 2.2 以降が必要

■クレジット

写真
- K-bimヒロ

開発
- 小酒井輝
- ento

販売
- ムーンシャイン・プロジェクト株式会社

著作権
- K-bimヒロ
- ムーンシャイン・プロジェクト株式会社

カテゴリー: 発売 タグ:

GHUnit と NSInvocation を使って非同期通信の単体テストをする

2009 年 12 月 1 日 ento コメントはありません

1. 通信への依存を切る

さて、アプリのコンテンツの5段階評価をサーバに送信して保存する機能を作っているとします。例えばこんなコードです:

@implementation StarService
 
- (void)star:(NSUInteger)pictureNumber count:(NSUInteger)count {
	// リクエストオブジェクトをつくる
	NSString *url = [NSString stringWithFormat:@"http://%@:%d/api/star/", serviceHostname, servicePort, nil];
	NSMutableURLRequest *theRequest=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]
											  cachePolicy:NSURLRequestUseProtocolCachePolicy
										  timeoutInterval:60.0];
	// ... ここで呼び出しパラメータやHTTPヘッダを設定 ...
	StarRequestDelegate *requestDelegate = [[StarRequestDelegate alloc] initWithService:self delegate:serviceDelegate];
	/* API呼び出し開始! */
	NSURLConnection *theConnection = [NSURLConnection connectionWithRequest:aRequest delegate:requestDelegate];
}
...
// API呼び出し用のNSURLConnectionデリゲート
@implementation StarRequestDelegate
 
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
	if (delegate && [(NSObject*)delegate respondsToSelector:@selector(starService:didFinishStar:)]) {
		/* APIが正常に終わったので、デリゲートのコールバックを呼ぶ */
		[delegate starService:service didFinishStar:receivedData];
	}
	[super connectionDidFinishLoading:connection];
}

こんなコードを見るとまず作りたくなるのは、同じインターフェイスだけれど、実際はネットワークにアクセスしないクラスです。そうですよね。そうすれば、アプリの他の部分を実装するときも、サーバを立てたりすることなく開発をちゃきちゃき進めることができます。

@implementation FakeStarService
 
- (void)star:(NSUInteger)pictureNumber count:(NSUInteger)count {
	/* デリゲートのコールバックを直接呼び出すNSInvocationをつくる */
	NSInvocation *invocation;
	[[NSInvocation retainedInvocationWithTarget:serviceDelegate invocationOut:&invocation]
	 starService:self didFinishStar:nil];
 
	/* ネットワーク遅延を装うためにさらにNSInvocationをかぶせる */
	NSInvocation *delayInvocation;
	[[NSInvocation retainedInvocationWithTarget:invocation invocationOut:&delayInvocation]
	 performSelector:@selector(invoke) withObject:nil afterDelay:delay];
	[delayInvocation performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:NO];
}

上の例では、偽のネットワーク遅延を実現するために、NSInvocationを2つ使っています。待て待て、NSInvocationを使うのはもっとめんどくさかったはず?たしかにその通りです。上のコードは ForwardedConstruction という拡張の助けを借りて書かれています。

iPhoneでこの拡張を使うには、リンク先からコードをダウンロードした上で、以下の変更を加える必要があります。

--- Downloads/NSInvocationForwardedConstruction/NSInvocation(ForwardedConstruction).h	2009-05-04 11:55:34.000000000 +0900
+++ NSInvocation(ForwardedConstruction).h	2009-12-02 10:17:07.000000000 +0900
@@ -11,7 +11,7 @@
 //  appreciated but not required.
 //
 
-#import <Cocoa/Cocoa.h>
+#import <UIKit/UIKit.h>
 
 @interface NSInvocation (ForwardedConstruction)
 
@@ -21,3 +21,10 @@
 	invocationOut:(NSInvocation **)invocationOut;
 
 @end
+
+#if (TARGET_OS_IPHONE)
+@interface NSObject (ForwardedConstruction)
+- (NSString *)className;
++ (NSString *)className;
+@end
+#endif
--- Downloads/NSInvocationForwardedConstruction/NSInvocation+ForwardedConstruction.m	2009-05-04 11:55:34.000000000 +0900
+++ NSInvocation(ForwardedConstruction).m	2009-12-02 10:17:43.000000000 +0900
@@ -12,7 +12,9 @@
 //
 
 #import "NSInvocation(ForwardedConstruction).h"
-#import <objc/objc-runtime.h>
+//#import <objc/objc-runtime.h>
+#import <objc/runtime.h>
+#import <objc/message.h>
 
 //
 // InvocationProxy is a private class for receiving invocations via the
@@ -376,4 +378,21 @@
 	return invocationProxy;
 }
 
+@end 
+
+#if (TARGET_OS_IPHONE)
+
+@implementation NSObject (ForwardedConstruction)
+
+- (NSString *)className
+{
+	return [NSString stringWithUTF8String:class_getName([self class])];
+}
++ (NSString *)className
+{
+	return [NSString stringWithUTF8String:class_getName(self)];
+}
+
 @end
+
+#endif

2. スレッドに注意する

単体テストフレームワークとして、GHUnitを使います。これは Objective-C 向けのフレームワークで、Mac OS X 10.5 と iPhone 2.x/3.x で動作します。テスト実行用のGUIも付いています。さらに、自分自身を独立したスレッドで動かす機能もあり、これが NSURLConnection がからむテストで効いてきます。

というのも、NSURLConnectionの内部仕様的に、メインスレッド上で接続開始メソッドを呼ばないといけないらしく、テストフレームワークに別スレッドで走ってもらうことで、ネットワーク関連のコードをメインスレッドで動かしつつ、テスト実行用UIもスムーズに使うことができます。

ということで辿り付いたのが以下の構成です:

// 実際にネットワーク接続するクラスでテストをするクラス。
// 偽クラスをテストするテストクラスも別にある
@implementation HttpNetTest
 
- (BOOL)shouldRunOnMainThread {
	/* GHUnitは別スレッドで */
	return NO;
}
 
- (void)test_send_star {
	[tester do_test_send_star:service];
}
 
@implementation StarServiceTests
 
- (void)do_test_send_star:(id)service {
	// NSInvocationをつくり、
	NSInvocation *invocation;
	[[NSInvocation retainedInvocationWithTarget:service invocationOut:&invocation]
	  star:0 count:1];
	/* メインスレッドで呼び出す */
	[invocation performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:NO];
 
	/* 終了を待つ */
	BOOL notTimeout = [AsyncTestHelper wait:service.delegate property:@selector(receivedDidFinishGetStarsCount) atLeast:1];
 
	/* アサートたち */
	GHAssertTrue(notTimeout, @"Should not timeout");
	GHAssertEquals((NSUInteger)1, [service.delegate receivedDidFinishStarCount], @"delegate should receive star callback");
}

3. 通信の終了を待つ

非同期通信のテストでやっかいなのが、いつ通信が終了したかを検知する必要がある点です。テストコードでは以下の部分になります。

@implementation StarServiceTests
 
- (void)do_test_send_star:(id)service {
	// ..
	[AsyncTestHelper wait:service.delegate property:@selector(receivedDidFinishStarCount) atLeast:1];
	// ..
}

このメソッドの中身は、ただ与えられたオブジェクトのプロパティが指定の値以上になるのを待つだけのものです:

@implementation AsyncTestHelper
 
+ (BOOL)wait:(id)target property:(SEL)getter atLeast:(NSUInteger)count {
	int tried = 0;
	while((NSUInteger)[target performSelector:getter]  10) {
			return FALSE;
		}
		[NSThread sleepForTimeInterval:0.5];
	}
	return TRUE;
}

テスト実行画面は以下のような感じ。

ghunit_test_runner

最後に、登場したクラス群の関係を示す簡単な図を作ってみました。XcodeのCore Dataモデリングツールを使用しています。

カテゴリー: 開発 タグ: