2013年1月23日水曜日

2つのModalViewを切り替えて表示する方法

ModalViewを起動している時に、一度ModalViewを閉じてすぐに他のModalViewを起動したい事があるかと思います。今回はその方法を書きます。
※iOS5以上での方法となります。

storyboard

まずstoryboardで起動元画面を1画面、ModalView用の2画面作成します。
左から以下の名前で進めていきます。
  • ViewController
  • ModalView1Controller
  • ModalView2Controller
ModalView2ControllerのStoryboardIDに「Modal2ViewController」と設定しておきます。

ModalView1Controller

1つ目のModalViewを実装していきます。
以下は ModalView1Controller.h
@protocol ModalView1ControllerDelegate
- (void)switchModalViewController:(UIViewController *)controller;
@end

@interface ModalView1Controller : UIViewController {
    id<ModalView1ControllerDelegate> myDelegate;
}

@property (nonatomic, retain) id myDelegate;
- (IBAction)showModalView2Controller:(id)sender; // storyboardに配置しているボタンのイベント
@end
次に ModalView1Controller.m
// 遷移するトリガー。ここではボタンクリックにしています
- (IBAction)showModalView2Controller:(id)sender
{
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard_iPhone" bundle:nil]; // MainStoryboard_iPhone.storyboard
    UINavigationController *nc = [storyboard instantiateViewControllerWithIdentifier:@"Modal2ViewController"]; // StoryboardIDを指定
    [myDelegate switchModalViewController:nc];
}
ここではDelegateを使って、遷移元に次に表示したいModalViewのControllerを渡している点がポイントです。

ViewController

次に1つ目の画面であるModalView起動画面を実装します。
以下は ViewController.m
// 遷移直前に呼ばれる
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    ModalViewController *controller = segue.destinationViewController;
    controller.myDelegate = self;

    // 上記はViewControllerに対して行う処理。Navigationとかは以下みたいにする
    // UINavigationController *navigationController = segue.destinationViewController;
    // MangaPageViewController *controller = (id)[[navigationController viewControllers] objectAtIndex:0];
}

#pragma mark - ModalView1ControllerDelegate
- (void)switchModalViewController:(UIViewController *)controller
{
    // 遷移先のModalViewを閉じて、次に表示させたいModalViewを起動
    [self dismissViewControllerAnimated:YES completion:^{
        [self presentViewController:controller animated:YES completion:NULL];
    }];
}
ポイント2つ。
  1. 遷移する時にModalView1Controllerで実装してるmyDelegateにselfを設定しておく。
  2. delegateメソッドが呼ばれたら表示中のModalView1Controllerを閉じ、閉じる処理が完了したらModalView2Controllerを起動させる。

完成

実装は終わりましたので確認してみてください。

2013年1月14日月曜日

iOS6以上でのstoryboard上のローカライズ対応


すっかりブログ書くことを忘れてたので初めての会社ブログへの投稿になります。鯱ブログだし休日に会社ブログ書くとらしい鯱れるね。

iOS6からstoryboard上のローカライズ対応が楽になりました!楽になった方法を書こうと思いますが、楽になったのは設定時であって前準備は非常にメンドウです。くじけぬ心を装備して臨みましょう。

Step1. プロジェクト作成

まずはXcodeでプロジェクトを作成してください。今回はiPhone/iPadのstoryboardを追加した状態で解説していきます。


Step2. Localizable.strings作成

Finderから「プロジェクト/en.lproj」ディレクトリに "Localizable.strings" ファイルを作成します。

今回の初期設定時に巻き込んで作ってしまうと楽なので含めている為、今回このファイルは使いません。不要ならこのStepは飛ばしてください。
コード上で以下のように記述する事で利用します。
NSLocalizedString(@"kye", @"comment");

Step3. Base.lproj作成

Xcodeで「Project > info> Localizations > + > Other > Base(Base)」を選択。
ローカライズ対象のファイルを選べというアナウンスがあるので、全てチェックが付いた状態で「Finish」を押します。


結果、Baseとenはこんな感じになります。

Step4. *.storyboard用の*.stringsファイル作成

ターミナルから「プロジェクト/Base.lproj」で以下のibtoolコマンドを実行します。それぞれstoryboardに対応したstringファイルなので、そのディレクトリにあるstoryboard名が異なれば内容変更して実施ください。
ibtool --export-strings-file MainStoryboard_iPhone.strings MainStoryboard_iPhone.storyboard 
ibtool --export-strings-file MainStoryboard_iPad.strings MainStoryboard_iPad.storyboard
こんな感じに*.storyboardに対し、*.stringファイルが増えていればOK。

Step5. *.stringsファイル移動

Base.lprojに作成した.*stringsファイルを、en.lprojディレクトリにFinder(実際のファイルをって事)で移動させます。
これでBase.lprojディレクトリに2ファイル、en.lprojディレクトリに4ファイルです。


Step6. Xcodeに今まで作成したファイルを追加

追加したLocalizable.stringsとstoryboardの*.stringファイルをXcode上に追加します。
Xcodeから「メニュー > Add Files to "プロジェクト名"」から"Base.lproj"と"en.lproj"を選択します。
Xcode上で*.storyboardとInfoPlist.stringsが重複して邪魔なので消します。

Step7. 対応言語の追加

英語以外の言語を追加していきます。今回は"Japanese(jp)"を選びます。

まローカライズ対象のファイルを選べというアナウンスがあるので、 *.storyboard以外の全てにチェックを付けた状態で「Finish」を押します。
"MainStoryboard_iPad.storyboard" や "MainStoryboard_iPhone.storyboard" ファイルにチェックを付けないのがポイントです。

これで、LanguageにJapaneseが増えます。

Xcode上で見ると "InfoPlist.strings", "Localizable.strings", "MainStoryboard_iPad.strings", "MainStoryboard_iPhone.strings" に▶印がついて、▼するとEnglishとJapaneseの2言語が設定出来る状態になりました。

これで前準備は終わりになります。慣れれば簡単なのかな?いあそんなことは...


Step8. storyboard上でUI作成

iPhoneのstoryboardを対応してみましょう。"MainStoryboard_iPhone.storyboard" を開いて適当にUI作成してください。
今回は以下のように作成してみました。

Step9. storyboardに表示するテキストをローカライズ対応

"MainStoryboard_iPhone.strings"ファイルの英語or日本語を開いて以下のようにkey-valueを設定していきます。
"key" = "value";
ここで重要なのはkeyの方です。keyは"MainStoryboard_iPhone.storyboard" を開いて、文字を表示させる対象の部品を選択し、storyboardの右Viewの左から3つ目にあるタブにある「Object ID」と値を設定したいプロパティ名になります。
もうひとつ大事なポイントとして、対象のプロパティには何かしらの文字を設定しておいてください。未設定だとkeyに対応したvalueが設定されません。


例えばUILabelの場合、私が作成したstoryboard上ではObject-IDが "udb-le-F0F" でした。これに表示させたい対象のプロパティ名 "title" を組み合わせた "udb-le-F0F.title" がkeyとなります。"MainStoryboard_iPhone.strings" 上には以下のように書きます。
"udb-le-F0F.title" = "Localize"; // 英語ファイル
"udb-le-F0F.title" = "ローカライズ"; // 日本語ファイル
なお、今回iPhoneだけstringファイルを弄りましたが、このままではiPad側のstringファイルに何も書かれていない為、エラーになってしまいます。たとえ未使用でも*.stringファイルには何か書いておく必要があるのでご注意を。
storyboard上に文字を挿入したい時はこのStepを毎回行う必要があります。


Step10. ローカライズされた事を確認

これでローカライズ対応は終わりました。言語表示が"英語"と"日本語"で検証してみてください。
切替方法は「Settingsアプリ > General > International > Language」となります。

もしうまく表示されない時はcleanするなり、アプリを一度削除する必要があります。


備考. 適当に試してみた

 

MainStoryboard_iPhone.strings(en.lproj)

/* UITabBarItemObject-IDUINavigationBar自体ではなく、Title部分のUIBarButtonItemな事に注意 */
"QxD-1d-LR4.title" = "Search";"hjG-GX-5Zj.title" = "Fav"; 
/* NavigationBar上のタイトル。Object-IDUINavigationBar自体ではなく、Title部分のUIBarButtonItemな事に注意 */
"udb-le-F0F.title" = "Localize"; 
/* UIBarButtonItem */
"HHM-r4-1XD.title" = "Push";
/* UILabel */
"3b5-Va-UMR.text" = "subakolab Inc."; 
/* UITextField */
"beM-F3-IQy.placeholder" = "hogehoge";"VKy-Ty-8Nf.text" = "input"; 
/* UIButton */
"Lrt-NR-GvK.normalTitle" = "tararara"; 

MainStoryboard_iPhone.strings(ja.lproj)

/* UITabBarItem */
"QxD-1d-LR4.title" = "検索";"hjG-GX-5Zj.title" = "お気に入り";
/* NavigationBar上のタイトル */
"udb-le-F0F.title" = "ローカライズ"; 
/* UIBarButtonItem */
"HHM-r4-1XD.title" = "押して"; 
/* UILabel */
"3b5-Va-UMR.text" = "株式会社スバコラボ"; 
/* UITextField */
"beM-F3-IQy.placeholder" = "ほげほげ";"VKy-Ty-8Nf.text" = "入力"; 
/* UIButton */
"Lrt-NR-GvK.normalTitle" = "たららら";


余談

 ブログに書くのが途中で面倒くさくなって投げそうになったのをグッと我慢して書いたのでゼヒゼヒお試しください。
何が面倒臭かったかと言うと今現在Bloggerのデザイン変更権限がアカウントに付与されてないせいで、ソースコードを綺麗にハイライトしてくれるjsを組み込めなかったせいで自分でハイライトさせた事ですね。そのままだと見難いし、でも面倒くさいしの間でたゆたってました。