woshidan's loose leaf

ぼんやり勉強しています

1.3 UIViewController1 UIViewController のカスタマイズ

元の資料よりコンパクトにしようと工夫していたはずが、気がついたら長くなってた。残念。

内容

注意:この記事では、見出しでは字数の都合で、UIViewControllerのサブクラスをSubUIViewControllerと表記し、本文中では具体的なクラス名で表記しています。

  • UIViewControllerの役割
  • UIViewControllerをカスタマイズするデザインツール
    • storyboard
    • xib
  • UIViewControllerのサブクラスの作成(共通部分)
  • storyboardでの作業
    • 画面の処理を扱うSubUIViewControllerのクラスファイルを作成し、そのクラスが扱うViewControllerを用意
    • 上記のViewControllerをstoryboardのInitial View Controllerに設定
    • ViewControllerにオブジェクトライブラリからパーツを選んで載せる
  • 各パーツと実装を結びつける
    • IBOutlet
      • SubUIViewController.hにプロパティを追加
      • storyboard上で紐づける操作
      • (void)viewDidLoadでプロパティからパーツの文字がいじれるかテストする
    • IBAction
      • IBActionを使ってSubUIViewController.mにメソッドの定義
      • メソッドとパーツアクションの結びつけ
  • 演習をやってみて
    • 間違ってOS X用のクラスを作る
    • メモリが足りなくなってstoryboardが固まる
    • 画面サイズのオプションを変更してしまいViewControllerに載せたパーツが見えない
    • Viewなどが出てくるタブがどこか5分くらい分からない
    • storyboard: .hと.m両方書かないのが少し気持ち悪い

1.3 UIViewController1 UIViewController のカスタマイズ

UIViewControllerはMVCでいうCで、iOSアプリケーションの画面の一単位として認識すると理解しやすいそうです。

UIViewControllerの役割

  • コンテンツを表示させる
  • 複数の UIViewController を管理するコンテナ
  • 他のViewControllerと連携する Modal

1.3で主に説明されているのは1つ目です。(3つ目が1.4で説明されています)

UIViewControllerをカスタマイズするデザインツール

ViewControllerを用いてコンテンツを表示するときは、たいてい、UIViewControllerを継承したクラスを作り、カスタマイズしていきます。

そのために使われるツールには、xibとstoryboardがあります(コードで書くことも出来ますが、主流ではありません)。

storyboard

複数のViewController間の連携や画面遷移などをよりデザインしやすくしたツールです。

xib

細かいパーツや再利用性の高いパーツのデザインを作る際に便利なツールです。昔はこちらが主流でしたが、いまは状況に合わせて、storyboardもxibも使用されます。

以下では、storyboard, xibを用いたコンテンツの表示をデザインする作業について説明します。

UIViewControllerのサブクラスの作成(共通部分)

storyboardでもxibでも、UIViewControllerのサブクラスを設定するところまでは一緒です。

  • Cmd+nまたはファイル > New > Fileで新しいファイルを作成をクリックし、CoCoa Touchクラスを作成します。
  • Choose options for your new file: というウィンドウが出てくるので、以下のように入力します(クラス名はmixi iOS Trainingの値に準じます)
Class MixiSampleViewController
Sub Class of UIVIewController
□ Also create XIB file ※
iphone
Language Objective-C

※ storyboardの場合はチェックをしない。xibの場合はチェックをすること。

Next > Createを押すと、新規ファイル MixiSampleViewController.hとMixiSampleViewController.mが作成されます。

以下では、storyboardでの作業についてまとめます。
xibについては、必要になったら、https://github.com/mixi-inc/iOSTraining/wiki/1.3-UIViewController1---UIViewController-%E3%81%AE%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA(xib,-autoresizing)を参照することにします。

storyboardでの作業

新規ファイルが作成できたら、次はstoryboard上で、新規ファイルに対して設定をしていきます。設定作業は

  • 画面の処理を扱うSubUIViewControllerのクラスファイルを作成し、そのクラスが扱うViewControllerを用意
  • 上記のViewControllerをstoryboardのInitial View Controllerに設定
  • ViewControllerにオブジェクトライブラリからパーツを選んで載せる

画面の処理を扱うSubUIViewControllerのクラスファイルを作成し、そのクラスが扱うViewControllerを用意

先ほど作成したUIViewControllerのサブクラスとは別にstoryboard上で新規ViewControllerを作成し、そのクラスにMixiSampleViewControllerのViewControllerを指定します。

Main.storyboardを選択します。
そして、右側のユーティリティエリアオブジェクトのライブラリからViewControllerを探しましょう。
見つかったら、ViewControllerを画面の中央の方へドラッグアンドドロップすることで、新しいViewController(中央エリアに四角い看板のように表示される)を作成します。

この新しいViewControllerをクリックして、右側のエリア上方、右から3番目のアイコンをクリック。
Classという欄にMixiSampleViewControllerと入力し、選択中のViewControllerのクラスが扱うクラスをMixiSampleViewControllerに変更します。

左側にSceneのリストを出しておいて、VIew Controller SceneがMixi Sample View Controller Sceneになったことを確認できたらOKだと思います。

ViewControllerをstoryboardのInitial View Controllerに設定

storyboardにはデフォルトで最初にロードされるViewController(=Initial View Controller)を設定できます。今回は、作成したViewControllerを起動時に最初にロードされるように設定します。

(なお、デフォルトでは、Initial View Controllerはプロジェクトを新規作成したときに自動生成されるViewControllerに指定されています)

前節の新規作成したViewControllerを選択した状態で、右側の左から4番目Attributes Inspectorを開きます。
すると、その中にis Initial View Controllerという項目があるので、そこにチェックを入れると、現在選択しているViewControllerがInitial View Controllerに設定されます。

中央の編集画面で矢印が現在選択しているViewController(=MixiSampleViewController)を指していればOKです。

ViewControllerにオブジェクトライブラリからパーツを選んで載せる

プログラミング的に言えば、ViewController1つにつき1つ割り当てられているUIViewインスタンスをカスタマイズしていることになるらしいです。

作業的には、右下のオブジェクトライブラリからUIViewControllerに載せたいパーツを載せたい位置にドラッグ&ドロップすればいい、という話になります。背景色はAttributes Inspector内の設定項目から変更できます。

ここまで出来たら一度実行してみて、シミュレータでカスタマイズしたView Controllerが表示されるか確認します。

各パーツと実装を結びつける

先ほど、storyboard上に作ったViewControllerのクラスとしてMixiSampleViewControllerを指定したので、ViewControllerが生成されるときには、MixiSampleViewControllerのインスタンスが生成されるようになっています。

なので、ViewControllerに置いたパーツを動かすためのコードはMixiSampleViewControllerクラスに作成される必要があります。

これから、動かしたいパーツに対して、最低限書く必要があると思われる特殊なキーワードを使うコード2種類とそのコードをstoryboard上でパーツと結びつける操作についてまとめます。

2種類のコードのうち、1つめは、ViewControllerからパーツを操作するために、パーツとクラスのプロパティを結びつけるためのIBOutletキーワードをつけたプロパティの宣言。
もう1つは、UI上のパーツに対してユーザーが起こしたアクション(=パーツアクション)に対応するIBActionのキーワードを使って宣言するメソッドです。

IBOutlet

SubUIViewController.hにプロパティを追加

コンテンツを載せているクラスのインターフェイスファイル MixiSampleViewController.hの@interface部にIBOutletキーワードを付けたUILabelのプロパティを作成します。

@interface MixiSampleViewController : UIViewController
@property (nonatomic, strong) IBOutlet UILabel *label;
// UILabelの部分(クラス名)はパーツの種類によって変更すべきです
@end

(MixiSampleViewController.mへの実装は後でInterface Builderでパーツとコードを結びつけるときになされるので、この段階で手動で行う必要はありません。)

storyboard上で紐づける操作

プロパティの宣言後、storyboardへ戻って、MixiSampleViewControllerを選択します。

そして、Document Outline(中央左側のファイル構成の部分のこと。View Controller Sceneの下側)のMixi Sample View Controllerを右クリックすると黒いパネルが出てきます。

Outletsという項目の中に、先ほど宣言したプロパティであるlabelが表示されているはずです。

labelの行の円をstoryboard上のViewControllerの中のラベルへドロップします。すると、storyboard上のUIのラベルと、MixiSampleViewControllerクラスのコードに書かれたプロパティlabelが結びつきます。

結びつくとこのパネル内でプロパティ名labelとパーツのId、Labelが結びついて表示されます。

(void)viewDidLoadでプロパティからパーツの文字がいじれるかテストする

ViewControllerで管理される画面が読み込まれたときに呼び出される(void)viewDidLoadメソッドの中に、labelのtextプロパティを書き換える処理を入れて、labelと結びついているラベルの文字列が変更するか確認しましょう。

- (void)viewDidLoad {
    [super viewDidLoad];
    self.label.text = @"Test";
}

IBAction

IBActionを使ってSubUIViewController.mにメソッドの定義

コンテンツを載せているクラスにMixiSampleViewController.mの@implementationの中にメソッドを定義します。

- (IBAction)buttonTapped:(id)sender
{
    self.label.text = @"YES";
}

このメソッドの戻り値はIBActionとなっていますが、これはInterface Builderが紐付けれるメソッドを探すためのキーワードです。実際に何かをreturnするのではなく、voidのようなものだそうです。

メソッドとパーツアクションの結びつけ

メソッドの宣言がつつがなく終了したら、先ほどと同様にDocument OutlineのMixi Sample View Controllerを右クリックして黒いパネルを出しましょう。

Received Actionsという項目にbuttonTapped:メソッドが追加されていますから、buttonTapped:の右側の円をドラッグしてButtonに結びつけましょう。

このとき、Buttonのどのアクションと結びつくかを聞かれるので、とりあえず今回は"Touch Up Inside"を選びます。 起動して、動作を確認してみましょう。

演習をやってみて

実は何をやっているのか、まとめたら疲れきって耳年増状態で本番を迎えたのでした。そして、その結果いろいろ楽しい感じになったのでした。

間違ってOS X用のクラスを作る

まず、間違ってOS X用のクラスを作っていて、<CoCoa/CoCoa.h> not foundとエラーが出て焦りました。

隣の席の方が自分もSwiftでやったよーと言ってくださって気が楽になりました。

メモリが足りなくなってstoryboardが固まる

次に、SampleProjectと自分のプロジェクトでXcodeを2つ立ち上げたら、シミュレータが起動画面で止まるようになり、さらには、storyboardが止まったので青くなりました(え)。

困ったら再起動する、よく覚えました。

画面サイズのオプションを変更してしまいViewControllerに載せたパーツが見えない

そして、対応していただいてもパーツが表示されないという……。

質問に対応していただいたときに、画面自体が表示されていることの確認の手順が勉強になりました。

(InitaiViewControllerを確認する、ViewControllerの背景を変更して、ViewController自体は表示されていることを確認する(パーツの設定がおかしいかVIewController全体の設定がおかしいのか))

ストーリーボードの時に下の方に表示している wAnyhAnyは複数サイズの画面でパーツを出しわけたいときに使うオプションみたいです。

Anyかエミュレータのデバイスに対応する画面サイズを指定していないと、そのViewControllerに載せたパーツは一切表示されないことも覚えました。

詳細は、

【iPhone6・iOS8】SizeClassesを使ったマルチデバイス対応 | スマホ研究部 by ブレイブソフト

です。

Viewなどが出てくるタブがどこか5分くらい分からない

とろい子なので、ViewやButtonなどが出てくるタブがどこにあるか、5分くらい悩みました。※演習時間は10分です。

ViewやButtonのタブは右下の方の、真ん中の円の中に□がある奴でした。

storyboard: .hと.m両方書かないのが少し気持ち悪い

肝心の演習内容については、演習やるまでの状態だと、

(MixiSampleViewController.mへの実装は後でInterface Builderでパーツとコードを結びつけるときになされるので、この段階で手動で行う必要はありません。) // 操作時要確認

コンテンツを載せているクラスにMixiSampleViewController.mの@implementationの中にメソッドを定義します。 // 作業時、ファイルをよく確認して修正すること

と書いてあって、なんだかヘッダファイルと実装ファイルの両方にメソッドを書かないことが気持ち悪かったみたいです。

今でも若干不安なのでまた復習しようと思います。作業の復習時間自体は短いですしね。

追記

iPhone - 第2回 mixi iOS Trainingまとめ - Qiita

見てたらIBOutletは別に.hに限定しなくてもいいみたい。privateっぽく書きたい場合は.mに書いたらいいいみたいです。

Xcode固まってよっぽど焦ってたのか、gitterのログ全然頭に入ってないみたいですね。