iPhoneアプリで画面遷移させる場合、コントローラをalloc/initしてナビゲーションコントローラのスタックにプッシュしたり、modalしたりする流れになるわけですが、複数の画面から呼ばれる画面だったりするとインスタンスの管理が面倒だったり、決まり文句をいちいち書くのが面倒になります。
そこでThree20のTTNavigatorを使うと、すっきり画面遷移できるようです。
webアプリ感覚で”http://about”のように遷移先を指定するだけで、その画面を表示できるようになります。
httpの部分は任意の文字列を定義できます。
そのためには、まずURLとコントローラのマッピングが必要です。
簡単にサンプルを示します。
#import "DCAppDelegate.h"
#import "DCTwitterController.h"
#import "DCGoogleReaderController.h"
#import "DCAboutController.h"
#import "DCTabBarController.h"
@implementation DCAppDelegate
- (void)applicationDidFinishLaunching:(UIApplication *)application {
TTNavigator *navigator = [TTNavigator navigator];
navigator.supportsShakeToReload = YES;
navigator.persistenceMode = TTNavigatorPersistenceModeTop;
TTURLMap *map = navigator.URLMap;
[map from:@"*" toViewController:[TTWebController class]];
[map from:@"dc://tab" toSharedViewController:[DCTabBarController class]];
[map from:@"dc://twitter" toViewController:[DCTwitterController class]];
[map from:@"dc://reader" toViewController:[DCGoogleReaderController class]];
[map from:@"dc://web" toViewController:[TTWebController class]];
[map from:@"dc://about" toViewController:[DCAboutController class]];
[map from:@"dc://compose?title=(compose:)" toModalViewController:[DCAboutController class]];
[navigator openURL:@"dc://tab" animated:NO];
}
- (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)URL {
[[TTNavigator navigator] openURL:URL.absoluteString animated:NO];
return YES;
}
@end |
まずTTNavigatorクラスのインスタンスを取得します。
TTNavigator.supportsShakeToReloadをYESにすると、iPhoneを振ると、リロードをしてくれるようになります。
TTNavigator.persistenceModeはアプリ終了時にどの画面を開いていたかを記憶する設定です。persistenceModeAllを指定すると常に最後に開いていた画面を記憶し、次回起動時にその画面を表示するようになります。
その後のTTURLMapがURLとコントローラのマッピング情報を保持するクラスです。
from:toViewControllerメソッドでは、fromに指定されたURLが呼ばれるとtoViewControllerの画面を表示する、というような設定になります。
fromに”*”を指定すると、マッピングにないURLが指定された場合のコントローラを指定できます。
URLを指定したら、TTNavigatorのopenURL:animated:メソッドを呼べば画面遷移が行われます。
TTNavigatorはシングルトンなため、どの画面からでも同一インスタンスを取得でき、遷移したい時にopenURL:animated:メソッドを呼んでやればよい、という感じです。
TabBarコントローラのような全画面で共通で使いたいコントローラの場合は
from:toSharedViewController:メソッドを使うと一つのインスタンスを使い回せるようです。
また、コントローラに渡すパラメータも指定できます。
[map from:@"dc://compose?subject=(compose:)" toModalViewController:[DCAboutController class]]; |
の部分がそれで、これはDCAboutControllerクラスのcompose:メソッドが呼ばれます。
パラメータの受け取りは以下のように行います。
#import "DCAboutController.h"
@implementation DCAboutController
- (void)createModel {
self.dataSource = [TTSectionedDataSource dataSourceWithObjects:
@"About",
[TTTableTextItem itemWithText:@"サイト" URL:@"http://iphone.longearth.net"],
[TTTableTextItem itemWithText:@"ご意見ご要望" URL:@"dc://compose?subject=%5biSlot%20Pro%5d%e6%84%8f%e8%a6%8b%2f%e8%a6%81%e6%9c%9b"],
[TTTableTextItem itemWithText:@"友達にすすめる" URL:@"dc://compose?subject=&body=http%3a%2f%2fitunes%2eapple%2ecom%2fWebObjects%2fMZStore%2ewoa%2fwa%2fviewSoftware%3fid%3d304074830%26mt%3d8"],
@"関連アプリ",
[TTTableTextItem itemWithText:@"iPachi" URL:@""],
[TTTableTextItem itemWithText:@"iSlot Pro" URL:@""],
[TTTableTextItem itemWithText:@"iTaskTimer" URL:@""],
nil];
}
- (UIViewController *)compose:(NSString *)subject query:(NSDictionary *)param {
TTMessageController* controller =
[[[TTMessageController alloc] init] autorelease];
controller.subject = subject;
controller.body = [param objectForKey:@"body"];
return controller;
}
@end |
第一引数にはsubjectで指定したものが、第二引数以降にも&繋ぎで複数パラメータが指定でき、中身はDictionaryとして取り出すことができます。
上の例ではパラメータを受け取り、それらの値を使って、メール送信画面を起動しているところです。
createModelメソッドはTTTableViewControllerでテーブルデータを表示する際に呼ぶメソッドで、ここではあまりふれません。
が、少しだけ触れておくと、TTTableViewControllerのdatasourceがテーブルデータとなり、TTSectionDataSourceを入れています。TTSectionDataSourceは引数にNSStringがあればそれをセクション名とし、それ以降のものをセクション内に属するデータとして扱います。それからそのデータとしてTTTableTextItemがあり、textで表示する文字を、URLでタップした時の遷移先を指定しています。以上でこんな画面になります。

URL形式での画面遷移でもすごい画期的なのに、まだまだThree20にはすごい部分が盛りだくさんです。
マジすごい。
タグ: iPachi, iphone, iSlot, iSlot Pro, iTaskTimer, NSString, objecti, objective-c, Three20, TTNavigator, twitter, UIViewController, アプリ, 画面遷移


11月 11th, 2009 at 7:05 AM
はじめまして、いつも楽しく読ませて頂いており、
また、自らの開発にも大変役立せて頂いています。
素晴らしいライブラリ、Three20もここで知りました。
しかし、、
是非私もThree20を使ってみたいと思い、色々調べていると、Three20を使用したアプリはAppStoreの審査でRejectされてしまうという情報を目にしました。。
なにやら、ライブラリ内でUITouchのprivateなAPIに直接アクセスしてしまっているところが原因だそうです。
該当する部分を削除することで、解決する(?)ようですが、
願わくばアップデートなどの対応をして頂きたいところですね。。
この件については、以下のサイトなどでディスカッションされてる模様です。
http://groups.google.com/group/three20/browse_thread/thread/c442af6e39a918b0/6d5046771539d139