● Carbon視点でiPhone探求(2009/12/13)

  この記事は、MOSAの会員にのみ読むことができるデベロッパー向けの
  ウェブサイトMOSADeN Onlineのに掲載された記事です。ほぼ一ヶ月
  遅れでここに掲載されて行きます

 〜 詳細ビューを表示するための準備 〜


前回は、画像(モデル)の削除と順序変更を実装してみました。続いて、テーブルビューに並んだ画像の名称変更を実現したいと思います。今回は、そのために必要となる新しいUIViewControllerの実装を解説します。

まず最初に、Interface Builder(v3.2.1)で画像情報の詳細(と言っても現在は名称だけ)を表示するためのUIViewControllerのnib(xib)ファイルを作成します。このビューコントローラの名称は「DetailViewController」とします。

  

ビュー上に、名称を入力するためのテキストフィールド(UITextField)を配置しただけの簡単な構成です。その左横にラベル(UILabel)で「名称」と表記しておきます。また、変更後の保存を実行するために、ナビゲーションバー上に配置する「保存」ボタン(UIBarButtonItem)もひとつ用意します。 ところで、UITextFieldは、数多くのアトリビュート(オプション)を持つコントロールのひとつです。こうしたアトリビュートはUITextField.hに定義されているプロパティと1対1で対応しています。以下の定義は、そのほんの一部です。

@property(nonatomic,copy) NSString *text;   // 入力済み文字
@property(nonatomic,retain) UIColor *textColor; // 文字カラー
@property(nonatomic,retain) UIFont *font;     // フォント種類とサイズ

こうしたプロパティに対してソースコードで値を代入すれば、アトリビュートを変更することができます。また、その初期値に関しては、Interface Builderのインスペクターウィンドウでも設定することができます。以下がインスペクターウィンドウで表示したUITextFieldクラスのアトリビュートです。

  

例えば、最初の「Text」アトリビュートは、先ほど示したNSStringのtextプロパティと一致しています。このカラムに文字列を入力しておけば、テキストフィールドが表示された時点で、その内容が代入されることになります。アトリビュートのタイトルを見れば、だいたいの設定内容は理解できるのですが、マウスカーソルをアトリビュート設定用コントロール上にしばらく静止させると、その説明がポップ表示されます(英語ですが...)。これを参考にすると良いでしょう。

  

ところが、これらのうち一番下の「Text Input Traits」タイトルで囲まれている7つのアトリビュートに関しては説明が表示されません。実は、これらはテキストフィールドのアトリビュートではなく(それが理由かどうかは定かではない)、UITextInputTraitsクラス(UITextInputTraits.h)に定義されている仮想キボードに対するアトリビュートなのです。以下が、7つのアトリビュートに対応する各プロパティの内容です。

@property(nonatomic) UITextAutocapitalizationType autocapitalizationType;
// 入力文字を自動で大文字に変換する作法を決める
@property(nonatomic) UITextAutocorrectionType autocorrectionType;
// 入力単語を自動で校正するかどうかを決める
@property(nonatomic) UIKeyboardType keyboardType;
// キーボードの種類を決める
@property(nonatomic) UIKeyboardAppearance keyboardAppearance;
// キーボードアピアランスを決める(Alertはバックが黒色)
@property(nonatomic) UIReturnKeyType returnKeyType;
// リターンキーの表示文字内容を決める
@property(nonatomic) BOOL enablesReturnKeyAutomatically;
// 文字入力がない時にリターンキーを使用可能にするかどうかを決める
@property(nonatomic,getter=isSecureTextEntry) BOOL secureTextEntry;
// パスワード入力モードにするかどうかを決める

例えば「Keybord」アトリビュートでは仮想キボードの種類を選ぶことができます。これを「Number Pad」と指定すれば、文字入力時にアルファベットキーボードの代わりにテンキーキーボードが表示されることになります。

実際のDetailViewController.h(クラス定義)は以下のような記述となります。Interface Builderでは、テキストフィールドと「保存」ボタンの両方を、ここに定義されているインスタンス変数(IBOutlet)へとリンクしておきます。

@class Model;

@interface DetailViewController : UIViewController <UITextFieldDelegate>
{
  IBOutlet UIBarButtonItem *de_save;  // 「保存」ボタン
  IBOutlet UITextField     *de_text;  // テキストフィールド
  Model           *de_model; // 表示対象モデル(画像)
}

@property (nonatomic, retain) Model  *de_model;

- (IBAction)saveName:(id)sender;

@end

このクラスは、文字入力でのリタンキーを制御するためのUITextFieldDelegateプロトコルにも準拠させます(次回に解説)。3つ目のインスタンス変数のde_modelは、詳細表示の対象となるモデルオブジェクト(Model)です。これは、RootViewControllerからDetailViewControllerを呼び出す時に渡されることになります。また、このクラスで定義されてるメソッドは「保存」ボタンをタップした時に実行されるsaveName:(アクションメソッド)ひとつだけです。

現状では、テーブルの行をタップすると、そこに登録されていた画像が表示されます。画像の名称を詳細ビューに表示させるためには、これとは別の方法を取る必要があります。そのため、行の右端に「アクセサリー」と呼ばれる小画像を表示させ、そこをタップすることで目的を達成します。 アクセサリーには以下の3種類あります。

typedef enum {
 UITableViewCellAccessoryNone, // 表示なし
 UITableViewCellAccessoryDisclosureIndicator, // (>)マーク
 UITableViewCellAccessoryDetailDisclosureButton, // 詳細丸ボタン
 UITableViewCellAccessoryCheckmark // チェックマーク
} UITableViewCellAccessoryType;

このうちUITableViewCellAccessoryDetailDisclosureButtonは青い丸ボタンを表示し、タップに反応してUITableViewのデリゲートを呼び出します。iPhone OS v2.xxでのアクセサリー表示はUITableViewのデリゲートで実現していましたが、この方法は、v3.xxから「DEPRECATED」(非推奨)となりました。代わりにセル(UITableViewCell)のプロパティであるaccessoryTypeへタイプ値を代入する方法が取られます。アプリの起動対象iPhone OSとしてv2.xxも考慮している方はご注意ください。

以前にRootViewController.hに実装した以下のデリゲートメソッドを少し修正し、アクセサリーの設定を追加します。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  Model      *model;
  UITableViewCell *cell;

  cell=[tableView dequeueReusableCellWithIdentifier:@"ImageCell"];
  if( ! cell )
    cell=[[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"ImageCell"] autorelease];
  if( model=[rt_array objectAtIndex:indexPath.row] )
  {
    cell.textLabel.text=model.md_name;
    cell.imageView.image=model.md_image;
    cell.accessoryType=UITableViewCellAccessoryDetailDisclosureButton;
    // アクセサリー(青丸の詳細ボタン)の表示を指示する
  }
  return cell;
}

アクセサリーをタップすると、以下のUITableViewのデリゲートが呼ばれます。ここに詳細ビュー(UIDetailViewController)への切り替え処理を実装します。

- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath;
{
  Model         *model;
  SymmetryAppDelegate *app;

  if( model=[rt_array objectAtIndex:indexPath.row] )  // 対象モデルを得る
  {
    app=[[UIApplication sharedApplication] delegate];
    [app pushDetailViewControllerWithModel:model]; //  詳細ビューを表示
  }
}

ビューコントローラをDetailViewControllerへと切り替える(プッシュする)メソッドはアプリケーションデリゲート(SymmetryAppDelegate.m)に実装します。また、作成したDetailViewControllerは、このクラスのap_detailvctrインスタンス変数へ保存します。加えて、表示を元に戻す(ポップする)メソッドもここに用意しておきます。

- (void)pushDetailViewControllerWithModel:(Model *)model
{
  if( ! ap_detailvctr ) // 詳細ビューコントロラー用インスタンス変数
    ap_detailvctr=[[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];
  if( ap_detailvctr )
  {
    ap_detailvctr.de_model=model; // 対象モデルを渡す
    [navigationController pushViewController:(UIViewController *)ap_detailvctr animated:YES];
  }
}

- (void)popViewController // ビューコントローラをポップする
{
  [navigationController popViewControllerAnimated:YES];
}

今回は、詳細ビュー表示の下準備としてDetailController.m以外のソースコード部分を説明しました。次回は、引き続きDetailViewControllerクラス(DetailViewController.m)の実装を解説いたします。

copyright 2009 Ottimo, Inc. All rights reserved
無断転載・引用禁止