UITableViewControllerとUICollectionViewControllerが必要な理由

こんにちは皆さん、私の名前はArtyomです。私はiOS開発者です。 今日は、UITableViewControllerとUICollectionViewControllerを使用する方法について説明します。



データのリスト表示を使用しないモバイルアプリケーションはほとんど見つかりません。 私たち(iOS開発者)はほとんどの場合、TableViewまたはCollectionViewを使用します。 開発速度と作成されたソリューションをさらにサポートするコストの理由から、これらの基本要素を使用するアプローチを選択することが非常に重要である理由です。 Touch Instinctの同僚と私たちが出会った結論を共有したいと思います。



この記事は、TableView(CollectionView)を使用する開発者を対象としていますが、何らかの理由でTableViewController(CollectionViewController)を使用することはできません。 TableView(コントローラー)のみを以下で説明しますが、書かれたすべてはCollectionView(コントローラー)にも適用されます。



オプション1:MassiveViewController



多くの人にとって最もシンプルで最も馴染みのあるオプションは、開発者がストーリーボードでViewControllerを作成し、TableViewをその上に配置して、UITableViewDelegateおよびUITableViewDataSourceプロトコルを実装するオブジェクトとしてViewControllerを示す場合です。









すべて順調ですが、常にではありません。 時々、問題が発生します。 また、TableViewとはほとんど関係のない追加のロジックがこのコントローラーに表示されるときに発生します。 UIBarButtonItemハンドラーがコントローラーに表示されていても問題ありません。 ただし、原則として、すべてがこのコントローラーに表示されます:TabieViewの下(上/左/右)のボタンハンドラー、さまざまなポップアップ要素、ネットワークの操作、セルの構成など。 単一責任の原則に重大な違反があります。 ViewControllerは悲しい...他の開発者は、そのような写真を見るとさらに悲しむ。



オプション2.固体



SOLIDに関する記事との最初の会議の後、普通の開発者は、さまざまな重大度の疑わしいアイデアを追求し始めます。 そのようなアイデアの1つは、単一責任の原則の広範な適用です。 含む、常識を損なう。



読み取りに感銘を受けた開発者は、次の図に示すように、各プロトコルの実装用に個別のオブジェクトを作成します。









しかし、このアプローチの問題は、UIKitがこの原則をサポートすることをしばしば困難にすることです。 実際、密接に相互接続されているものはバリケードの異なる側にあることが判明しています。 基本的な例:セルの高さを計算するとき(デリゲート)、その内容(データソース)を知る必要があります。 最終的に、すべてが以前のバージョンよりもさらに混乱する可能性があります。



オプション3.半固体



開発者は、Solidバージョンの使用には特定の困難があることに気づき、それをわずかに簡素化することにしました。 これを行うには、2つのクラスを作成するのではなく、DelegateおよびDataSourceプロトコルを実装するクラスを作成します。 このオプションは実装が簡単ですが、欠点もあります。追加のクラスを作成し、ViewControllerとプロトコルを実装するオブジェクト間の双方向通信を提供する必要があります。











実際、すべてがシンプルです



むかしむかし、彼らはこの問題について同僚と話し合った。 そして、ある経験豊富な開発者は、次のように述べています。 すべてが箱から出されます。」



そして確かにあります。 何らかの理由で、多くの開発者はTableViewControllerを使用せず、必要に応じてビューに配置できる別のTableViewがあると主張しています。 私は2つの引数でこれに答えたいです:



  1. ほとんどの場合、TableViewはビュー全体に広がります。TableViewControllerをすぐに使用する方が簡単ではありませんか?
  2. TableViewがビュー全体に配置されていない場合、他の要素が存在し、それらに関連付けられたコードがViewControllerに表示されます。


TableViewコードが、ViewControllerが担当する他の要素のコードと混合されていることは、何も良いことではありません。 iPadアプリケーションの場合、1つのViewControllerで処理される3つ以上のテーブルが画面上にある場合、画像がどれだけ悪化しているか想像してください。



私が検討することを提案するアプローチは、堅実さと単純さの間の妥協です。 それは、別々に横たわるTableViewの拒否にあります。 iOSおよびXcodeの最新バージョンでは、このアプローチを苦痛や苦痛を伴わずに、利便性と喜びで適用できます。









多くの人は、ViewControllerを作成するというアイデアを好まないでしょうが、実際には、実際に必要な場所にのみ表示されます。 たとえば、タスクはテーブルを全画面にすることです。 この目的には、TableViewControllerをすぐに使用することをお勧めします。 同じテーブルを別の場所に追加する必要がある場合は、このTableViewControllerを簡単に再利用できます。 テーブルロジックのみがあり、それ以上のものはありません。



TableViewの場所を突然変更する必要がある場合は、TableViewControllerを統合する(ViewController Containmentを介して)別のViewControllerを作成するだけです。 このソリューションは、すべてがストーリーボードを介して実行できるようにボックス化されています。









また、統合されたViewControllersは、統合されたコンテナに応じてサイズを変更します。これは、このソリューションの「ボックス性」をもう一度確認してください。



コードでも同じことができます。



let embedController = UIViewController() addChildViewController(embedController) view.addSubview(embedController.view) embedController.view.frame = view.bounds //    Auto Layout,      embedController.didMoveToParentViewController(self)
      
      





特別な見出し:バックフィルの質問!



embedController.willMoveToParentViewController(self)



呼び出さないのはなぜですか?



正解
このメソッドは内部的に呼び出されます。
 addChildViewController(embedController)
      
      





組み込みのViewControllerを削除する場合、すべてが逆に発生することに注意してください。



 embedController.willMoveToParentViewController(nil) embedController.view.removeFromSuperview() embedController.removeFromParentViewController()
      
      





そして、 embedController.didMoveToParentViewController(self)



メソッドが自動的に呼び出されます。



さらに進みます。



率直に言って、私自身は不要なViewControllerを作成したくないので、テーブルに直接適用されないかもしれないが、それでも別個のViewControllerに値しない要素がいくつかあります。





今それと一緒に暮らすには?



ParentViewControllerからChildViewControllerに何かを渡す必要がある場合は、prepareForSegueメソッドをオーバーライドする必要があります。



 private var someController: SomeViewController! override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { if let someController = segue.destinationViewController as? SomeViewController { self.someController = someController } }
      
      





最後に、非常に明白なヒント



ViewControllerをあらゆる種類のゴミで詰まらせる必要はありません。 画面上の要素に適用されないロジックはレンダリングする必要があります。 幸い、ほとんどすべての人が知っているように、これらのセルのクラスにセル構成コードを配置することをお勧めします。



 func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { if let cell = cell as? SomeCell { cell.textLabel = someObject.someText //  cell.numberLabel = someObject.someNumber //  cell.configureForObject(someObject) //  } else if let cell = cell as? OtherCell { cell.textLabel = otherObject.text //  cell.numberLabel = otherObject.number //  cell.configureForObject(otherObject) //  } }
      
      





まとめ






All Articles