iOSユーザーインターフェイス:ストーリーボードとNIBとカスタムコード

公開: 2022-03-11

iOS開発者が同じ重要な質問のいくつかの変形を尋ねるのをよく耳にします:

iOSでUIを開発するための最良の方法は何ですか:ストーリーボード、NIB、またはコードを使用しますか?

この質問への回答は、明示的または暗黙的に、開発前に相互に排他的な選択が行われると想定する傾向があります。これは、多くの場合、事前に対処されます。

私は、答えは代わりに1つ以上の反対の質問の形を取るべきだと思います。

「最高の」車は何ですか?

トピック外の例で説明しましょう。 車を購入したいとします。簡単な質問が1つあります。「最良の選択は何ですか?」

モデル、さらにはブランドを提案することで本当に答えることができますか? あなたがフェラーリを提案しない限り、ありそうもない。 代わりに、次のような他のいくつかの質問で答えるでしょう。

  • あなたの予算はいくらですか?
  • 何席必要ですか?
  • 燃費は気になりますか?
  • スポーツカーについてどう思いますか?

適切な状況に置かれない限り、良い車や悪い車などは存在しないことは明らかです。特定のニーズに基づいて、良い車や悪い車が存在するだけです。

iOSUIデザインに戻る

私たちの車の問い合わせと同じように、 「iOSUIを開発するための最良の方法は何ですか」という質問には文脈が欠けています。 そして驚くべきことに、答えは万能の場合である必要はありません。

大まかに言えば、採用できるユーザーインターフェイスデザインアプローチには3つのタイプがあり、それぞれに長所と短所、ファンと嫌いがあります。

  • iOSストーリーボード:複数のアプリケーションビューとそれらの間の遷移をレイアウトするためのビジュアルツール。
  • NIB(またはXIB) :各NIBファイルは単一のビュー要素に対応し、Interface Builderでレイアウトできるため、ビジュアルツールにもなります。 「NIB」という名前はファイル拡張子に由来していることに注意してください(以前は.nibでしたが、現在は.xibですが、古い発音は残っています)。
  • カスタムコード:つまり、GUIツールはありませんが、すべてのカスタムポジショニング、アニメーションなどをプログラムで処理します。

これらのオプションはどれも、他のどのオプションよりも普遍的に優れているわけではありません(聞こえるかもしれませんが)。

たとえば、ストーリーボードはiOSUIツールキットに追加された最新のものです。 それらは未来であり、NIBとカスタムコードUIに取って代わると言われています。 ストーリーボードは便利なツールだと思いますが、 NIBやカスタムコードを補完するものほどではありません。 ストーリーボードは、すべてではありませんが、一部の状況では正しい選択です。

このiOS開発チュートリアルは、iOSUIデザインへの3つのアプローチの違いを探求することを目的としています。

さらに、(同じプロジェクトで)すべてを使用できるのに、目前の特定の問題に最適なメカニズムを選択して、静的に1つのオプションに固執する必要があるのはなぜですか?

これは、私の意見では、より高いレベルで一般化できる質問であり、その答えは、ソフトウェア開発の原則のリストで上位にランク付けされています。すべての人にとって普遍的な最良の選択である普遍的な言語、フレームワーク、またはテクノロジーはありませんソフトウェア開発の問題。 同じことがiOSUIデザインにも当てはまります。

このiOS開発チュートリアルでは、これらの各方法を検討し、それらを使用する必要がある場合と使用しない場合のユースケース、およびそれらをブレンドする方法を紹介します。

iOSストーリーボード

古典的な初心者の間違いは、プロジェクト全体で1つの大規模なiOSストーリーボードを作成することです。 私もストーリーボードを使い始めたときにこの間違いを犯しました(おそらくそれは魅力的なルートだからです)。

古典的な初心者の間違いは、プロジェクト全体で1つの巨大なストーリーボードを作成することです。 ストーリーボードは、ストーリーを伝えるボードです。 無関係なストーリーを1つの大きなボリュームに混ぜるために使用するべきではありません。

その名前が示すように、ストーリーボードはストーリーを伝えるボードです。 無関係なストーリーを1つの大きなボリュームに混ぜるために使用するべきではありません。 ストーリーボードには、論理的に相互に関連するビューコントローラが含まれている必要があります。これは、すべてのビューコントローラを意味するわけではありません。

たとえば、以下を処理するときにストーリーボードを使用することは理にかなっています。

  • 認証と登録のための一連のビュー。
  • マルチステップの注文入力フロー。
  • ウィザードのような(つまり、チュートリアル)フロー。
  • ビューのマスター/詳細セット(プロファイルリスト、プロファイル詳細など)。

一方、単一のアプリ全体のストーリーボードを含む大きなストーリーボードは避ける必要があります(アプリが比較的単純でない限り)。 深く掘り下げる前に、その理由を見てみましょう。

大きなiOSストーリーボードの愚かさ

大規模なストーリーボードは、参照と保守が難しいことを除けば、チーム環境に複雑さの層を追加します。複数の開発者が同じストーリーボードファイルで同時に作業する場合、ソース管理の競合は避けられません。 ストーリーボードは内部的にテキストファイル(実際にはXMLファイル)として表されますが、マージは通常重要です。

開発者がソースコードを見るとき、彼らはそれを意味的な意味に帰します。 したがって、手動でマージする場合、競合の両側を読んで理解し、それに応じて行動することができます。 代わりに、ストーリーボードはXcodeによって管理されるXMLファイルであり、コードの各行の意味は必ずしも理解しやすいとは限りません。

非常に簡単な例を見てみましょう。2人の異なる開発者がUILabelの位置を変更し(autolayoutを使用)、後者が変更をプッシュして、次のような競合を生成するとします(競合するid属性に注意してください)。

 <layoutGuides> <viewControllerLayoutGuide type="top"/> <viewControllerLayoutGuide type="bottom"/> </layoutGuides> <layoutGuides> <viewControllerLayoutGuide type="top"/> <viewControllerLayoutGuide type="bottom"/> </layoutGuides>

id自体は、その真の意味については何も示していないため、操作する必要はありません。 唯一の意味のある解決策は、対立の2つの側面の一方を選択し、もう一方を破棄することです。 副作用はありますか? 知るか? あなたではありません。

これらのiOSインターフェイス設計の問題を緩和するには、同じプロジェクトで複数のストーリーボードを使用することをお勧めします。

ストーリーボードを使用する場合

ストーリーボードは、相互接続された複数のView Controllerで使用するのが最適です。これは、ViewController間の移行が主な単純化であるためです。 ある程度、それらは、ビューコントローラ間の視覚的および機能的なフローを備えたNIBの構成と考えることができます。

ストーリーボードは、相互接続された複数のView Controllerで使用するのが最適です。これは、ViewController間の移行が主な単純化であるためです。

ナビゲーションフローを容易にすることに加えて、別の明確な利点は、ビューコントローラをポップ、プッシュ、表示、および閉じるために必要な定型コードを排除することです。 さらに、View Controllerは自動的に割り当てられるため、手動でallocinit化する必要はありません。

最後に、ストーリーボードは複数のビューコントローラーが関係するシナリオに最適ですが、次の3つの理由から、単一のテーブルビューコントローラーを使用する場合はストーリーボードを使用することもできます。

  • テーブルセルのプロトタイプをインプレースで設計する機能は、ピースをまとめるのに役立ちます。
  • 親テーブルビューコントローラ内で複数のセルテンプレートを設計できます。
  • 静的なテーブルビューを作成することは可能です(残念ながらストーリーボードでのみ利用可能な待望の追加)。

NIBを使用して複数のセルテンプレートを設計することもできると主張する人もいるかもしれません。 実のところ、これは好みの問題です。一部の開発者はすべてを1つの場所に置くことを好みますが、他の開発者は気にしません。

iOSストーリーボードを使用しない場合

いくつかのケース:

  • ビューのレイアウトは複雑または動的であり、コードを使用して実装するのが最適です。
  • ビューはすでにNIBまたはコードで実装されています。

このような場合、ストーリーボードからビューを除外するか、ビューコントローラーに埋め込むことができます。 前者はストーリーボードの視覚的な流れを壊しますが、機能や開発に悪影響を与えることはありません。 後者はこの視覚的な流れを保持しますが、ビューはビューコントローラーに統合されていないため、追加の開発作業が必要です。コンポーネントとして埋め込まれているだけなので、ビューコントローラーはビューを実装するのではなく対話する必要があります。

一般的な長所と短所

ストーリーボードがiOSUIデザインでいつ役立つかがわかったので、このチュートリアルでNIBに進む前に、ストーリーボードの一般的な長所と短所を見ていきましょう。

プロ:パフォーマンス

直感的には、ストーリーボードが読み込まれると、そのすべてのビューコントローラーがすぐにインスタンス化されると想定できます。 幸い、これは単なる抽象化であり、実際の実装には当てはまりません。代わりに、初期のViewController(存在する場合)のみが作成されます。 他のViewControllerは、セグエが実行されるとき、またはコードから手動でインスタンス化されます。

プロ:プロトタイプ

ストーリーボードは、ユーザーインターフェイスフローのプロトタイピングとモックアップを簡素化します。 実際、ビューとナビゲーションを備えた完全に機能するプロトタイプアプリケーションは、ストーリーボードと数行のコードを使用して簡単に実装できます。

短所:再利用性

移動やコピーに関しては、iOSストーリーボードの位置が適切ではありません。 ストーリーボードは、依存するすべてのビューコントローラと一緒に移動する必要があります。 つまり、単一のビューコントローラを個別に抽出して、単一の独立したエンティティとして他の場所で再利用することはできません。 機能するのはストーリーボードの残りの部分に依存します。

短所:データフロー

多くの場合、アプリの移行時にViewController間でデータを渡す必要があります。 ただし、この場合、Interface Builderで発生した痕跡がないため、ストーリーボードの視覚的な流れは壊れています。 ストーリーボードは、View Controller間のフローの処理を処理しますが、データのフローは処理しません。 したがって、宛先コントローラーは、視覚的なエクスペリエンスをオーバーライドするコードで構成する必要があります。

ストーリーボードは、View Controller間のフローの処理を処理しますが、データのフローは処理しません。

このような場合、次のようなif /else-ifスケルトンを持つprepareForSegue:senderに依存する必要があります。

 - (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { NSString *identifier = [segue identifier]; if ([identifier isEqualToString@"segue_name_1"]) { MyViewController *vc = (MyViewController *) [segue destinationViewController]; [vc setData:myData]; } else if ([identifier isEqualToString@"segue_name_2"]) { ... } else if ... }

このアプローチはエラーが発生しやすく、不必要に冗長であることがわかりました。

NIB

NIBは、iOSインターフェイスデザインを実行するための古い(より)方法です。

この場合、「古い」は「悪い」、「時代遅れ」、または「非推奨」を意味するものではありません。 実際、iOSストーリーボードはNIBの普遍的な代替品ではないことを理解することが重要です。 場合によっては、UIの実装を単純化するだけです。

NIBを使用すると、任意のビューを設計でき、開発者は必要に応じてビューコントローラーに接続できます。

オブジェクト指向設計をUIに適用する場合、ビューコントローラのビューを個別のモジュールに分割することは理にかなっています。各モジュールは、独自のNIBファイル(または同じファイルにグループ化された複数のモジュール)を持つビューとして実装されます。 このアプローチの明らかな利点は、各コンポーネントの開発、テスト、およびデバッグが容易なことです。

NIBは、ストーリーボードで見たマージの競合の問題を共有しますが、NIBファイルは小規模で動作するため、程度は低くなります。

iOSUIデザインにNIBを使用する場合

すべてのユースケースのサブセットは次のようになります。

  • モーダルビュー
  • シンプルなログインおよび登録ビュー
  • 設定
  • ポップアップウィンドウ
  • 再利用可能なビューテンプレート
  • 再利用可能なテーブルセルテンプレート

その間…

NIBを使用しない場合

次の目的でNIBを使用することは避けてください。

  • 動的コンテンツを含むビュー。コンテンツに応じてレイアウトが大幅に変更されます。
  • 本質的にInterfaceBuilderで簡単に設計できないビュー。
  • ストーリーボードを使用して簡略化できる複雑なトランジションを備えたビューコントローラー。

一般的な長所と短所

より一般的には、NIBを使用することの長所と短所を見ていきましょう。

プロ:再利用性

NIBは、同じレイアウトが複数のクラスで共有されている場合に便利です。

単純な使用例として、ユーザー名とパスワードのテキストフィールドを含むビューテンプレートを、同じNIBから発信された架空のTTLoginViewビューとTTSignupViewビューを使用して実装できます。 TTLoginViewはパスワードフィールドを非表示にする必要があり、両方とも対応する静的ラベル(「ユーザー名の入力」と「パスワードの入力」など)を指定する必要がありますが、ラベルは同じ基本機能と同様のレイアウトを持ちます。

長所と短所:パフォーマンス

NIBは遅延ロードされるため、必要になるまでメモリを使用しません。 これは利点になる可能性がありますが、遅延読み込みプロセスには待ち時間があり、欠点もあります。

iOSカスタムコード(プログラムUI)

ストーリーボードとNIBで実行できるiOSインターフェイスデザインは、生のコードで実装することもできます(もちろん、開発者がそのような豊富なツールセットの贅沢を持っていなかった時代がありました)。

NIBやストーリーボードでは実行できないことは、常にコードで実装できます。

おそらくもっと重要なのは、NIBやストーリーボードでは実行できないことを、技術的に実現可能であれば、常にコードで実装できることです。 別の見方をすれば、NIBとストーリーボードはコードで実装されているため、それらの機能は当然サブセットになります。 長所と短所に直接飛び込みましょう。

プロ:フードの下で

iOS UIをプログラムで作成する最大の利点は、ユーザーインターフェイスのコーディング方法を知っていれば、内部で何が起こるかを知っていることですが、NIBやストーリーボードについては必ずしもそうとは限りません。

比較するには:電卓は便利なツールです。 しかし、手動で計算を実行する方法を知っていることは悪いことではありません。

これはiOSに限定されるものではなく、あらゆるビジュアルRADツール(たとえば、Visual StudioやDelphiなど)に限定されません。 ビジュアルHTMLRAD環境は、典型的な境界のケースを表しています。HTMLの知識は不要であり、すべてを視覚的に実行できると主張して、(多くの場合、記述が不十分な)コードを生成するために使用されます。 しかし、Web開発者は、手を汚さずにWebページを実装することはできません。生のHTMLとCSSを手動で処理すると、よりモジュール化された、より効率的なコードにつながることを知っています。

そのため、iOSユーザーインターフェイスのコーディングをマスターすることで、これらの要素がどのように組み合わされるかをより細かく制御し、認識を深めることができます。これにより、開発者としての上限が引き上げられます。

プロ:コードが唯一のオプションである場合

カスタムiOSコードがUIデザインの唯一のオプションである場合もあります。 ビュー要素が移動し、フローまたはレイアウトがコンテンツに基づいて大幅に調整される動的レイアウトが典型的な例です。

プロ:競合のマージ

NIBとストーリーボードはマージの競合に大きく悩まされていましたが、コードに同じ障害はありません。 すべてのコードには意味的な意味があるため、競合の解決は通常よりも難しくありません。

短所:プロトタイピング

レイアウトが実際に動作するのを見るまで、レイアウトがどのように見えるかを理解するのは困難です。 さらに、ビューとコントロールを視覚的に配置することはできないため、レイアウト仕様を具体的なビューに変換するのにかかる時間は、物事がどのようにレンダリングされるかを即座にプレビューできるNIBやストーリーボードと比較してはるかに長くなります。

短所:リファクタリング

ずっと前に、または他の誰かによって書かれたコードのリファクタリングも、はるかに複雑になります。要素がカスタムメソッドとマジックナンバーを使用して配置およびアニメーション化されると、デバッグセッションが困難になる可能性があります。

プロ:パフォーマンス

パフォーマンスの観点から、ストーリーボードとNIBは、ロードと解析のオーバーヘッドの影響を受けます。 そして最終的に、それらは間接的にコードに変換されます。 言うまでもなく、これはコードで作成されたUIでは発生しません。

プロ:再利用性

プログラムで実装されたビューは、再利用可能な方法で設計できます。 いくつかのユースケースを見てみましょう。

  • 2つ以上のビューは共通の動作を共有しますが、わずかに異なります。 基本クラスと2つのサブクラスが問題をエレガントに解決します。
  • 単一のコードベースを作成することを目的として、プロジェクトをフォークする必要がありますが、それぞれ特定のカスタマイズを使用して2つ(またはそれ以上)の異なるアプリケーションを生成します。

同じUI設計プロセスは、NIBとストーリーボードでははるかに複雑になります。 テンプレートファイルでは継承が許可されておらず、可能な解決策は次のとおりです。

  • NIBファイルとストーリーボードファイルを複製します。 その後、彼らは別々の生活をし、元のファイルとは関係がありません。
  • 外観と動作をコードでオーバーライドします。これは単純な場合には機能する可能性がありますが、他の場合には重大な問題を引き起こす可能性があります。 コードによる大量のオーバーライドは、ビジュアルデザインを役に立たなくし、頭痛の種になる可能性があります。たとえば、特定のコントロールがInterface Builderで一方向に表示されても、アプリの実行中はまったく異なって見える場合などです。

コードを使用する場合

次のような場合は、iOSユーザーインターフェイスの設計にカスタムコードを使用することをお勧めします。

  • 動的レイアウト。
  • 丸みを帯びた角、影などの効果のあるビュー。
  • NIBとストーリーボードの使用が複雑または実行不可能な場合。

コードを使用しない場合

一般に、コードで作成されたUIは常に使用できます。 彼らはめったに悪い考えではないので、私はここ。

NIBとストーリーボードはテーブルにいくつかの利点をもたらしますが、コードの使用を思いとどまらせるためにリストに入れることには合理的な欠点はないと思います(おそらく怠惰を除いて)。

1つのプロジェクト、複数のツール

ストーリーボード、NIB、およびコードは、iOSユーザーインターフェイスを構築するための3つの異なるツールです。 それらを持っていることは幸運です。 プログラマティックUIの狂信者は、おそらく他の2つのオプションを考慮に入れていません。コードを使用すると、技術的に可能なすべてのことを実行できますが、代替手段には制限があります。 そこにいる残りの開発者のために、Xcodeアーミーナイフは同じプロジェクトで同時に効果的に使用できる3つのツールを提供します。

どのように、あなたは尋ねますか? あなたの好きなように。 考えられるアプローチは次のとおりです。

  • 関連するすべての画面を個別のグループにグループ化し、各グループに独自のストーリーボードを実装します。
  • テーブルビューコントローラ内のストーリーボードを使用して、再利用できないテーブルセルをインプレースで設計します。
  • 再利用を促進し、繰り返しを避けるために、NIBで再利用可能なテーブルセルを設計しますが、カスタムコードを介してこれらのNIBをロードします。
  • NIBを使用して、カスタムビュー、コントロール、および中間オブジェクトを設計します。
  • 非常に動的なビュー、より一般的にはストーリーボードとNIBを介して簡単に実装できないビューにコードを使用し、ストーリーボードにビューの遷移を格納します。

最後に、すべてを結び付ける最後の例を見てみましょう。

シンプルなユースケース

いくつかの異なるビューを持つ基本的なメッセージングアプリを開発したいとします。

  • フォローしている友達のリスト(将来のリスト全体でUIの一貫性を保つための再利用可能なセルテンプレートを使用)。
  • 個別のセクション(プロファイル情報、統計、ツールバーを含む)で構成されるプロファイル詳細ビュー。
  • 友人との間で送受信されるメッセージのリスト。
  • 新しいメッセージフォーム。
  • ユーザーメッセージで使用されているさまざまなタグを表示するタグクラウドビュー。各タグのサイズは、使用された回数に比例します。

さらに、ビューが次のように流れるようにします。

  • フォローしている友達のリストの項目をクリックすると、関連する友達のプロフィールの詳細が表示されます。
  • プロファイルの詳細には、プロファイル名、アドレス、統計、最新のメッセージの短いリスト、およびツールバーが表示されます。

このiOSアプリを実装するには、次の3つのUIツールすべてが便利です。

  • 4つのビューコントローラ(リスト、詳細、メッセージのリスト、および新しいメッセージフォーム)を備えたストーリーボード。
  • 再利用可能なプロファイルリストセルテンプレート用の個別のNIBファイル。
  • プロファイルの詳細ビュー用の3つの個別のNIBファイル(プロファイルの詳細、統計、最後の3つのメッセージ)を構成する個別のセクションごとに1つ、保守性を向上させます。 これらのNIBはビューとしてインスタンス化され、ビューコントローラーに追加されます。
  • タグクラウドビューのカスタムコード。 このビューは、StoryBoardsでもNIBでも、InterfaceBuilderで設計できない典型的な例です。 代わりに、コードを介して完全に実装されます。 ストーリーボードの視覚的な流れを維持するために、ストーリーボードに空のビューコントローラーを追加し、タグクラウドビューをスタンドアロンビューとして実装し、プログラムでビューをビューコントローラーに追加することを選択します。 明らかに、ビューはスタンドアロンビューとしてではなく、View Controller内に実装することもできますが、再利用しやすいように分離しておく必要があります。

本当に基本的なモックアップは次のようになります。

この図は、ストーリーボード、NIB、およびカスタムiOSコードを使用する1つのiOSユーザーインターフェイス設計プロジェクトを示しています。

それで、コアビューがUIデザインへの3つの主要なアプローチを結び付ける適度に洗練されたiOSアプリの基本的な構造について概説しました。 各ツールには長所と短所があるため、二者択一の決定はありません。

まとめ

このチュートリアルで検討したように、ストーリーボードはiOSUIデザインとビジュアルフローに顕著な簡素化を追加します。 また、定型コードを排除します。 しかし、これはすべて、柔軟性を備えた代償を伴います。 一方、NIBは、単一のビューに焦点を当てることで柔軟性を高めますが、視覚的な流れはありません。 もちろん、最も柔軟な解決策はコードです。これは、やや不親切で本質的に非視覚的である傾向があります。

この記事に興味をそそられた場合は、レイウェンダーリッヒからの素晴らしい討論をご覧になることを強くお勧めします。これは、NIB、ストーリーボード、およびコードで作成されたUISのディスカッションに55分間費やされました。

最後に、1つ強調したいのは、不適切なiOSUIデザインツールの使用を絶対に避けてください。 ビューがストーリーボードで設計できない場合、またはビューをNIBまたはコードでより簡単な方法で実装できる場合は、ストーリーボードを使用しないでください。 同様に、ビューがNIBを使用して設計できない場合は、NIBを使用しないでください。 これらのルールは単純ですが、開発者としての教育に大いに役立ちます。