Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

ContainerViewとStoryboardとSwift3.0の交響曲(シンフォニー)

2,668 views

Published on

AKIBA.swift 第5回の登壇資料になります。
ContainerViewとStoryboardの特徴や特性をフル活用して、ライブラリにも決して引けを取らないようなUIを作成するためのヒントとなる部分や実装例・ポイントとなる部分をまとめました。

また、今回はXCode8 + Swift3.0での書き直しも一緒に行った際の注意したい点や変更点等も合わせて掲載しました。

【解説記事】
http://qiita.com/fumiyasac@github/items/17cbcffd90deee2cff43
【Swift3.0書き直し時の解説】
http://qiita.com/fumiyasac@github/items/3218c35de5e59f3bfafa
【サンプルコード】
https://github.com/fumiyasac/FundamentalContainerView

Published in: Technology
  • Be the first to comment

ContainerViewとStoryboardとSwift3.0の交響曲(シンフォニー)

  1. 1. ContainerViewとStoryboardとSwift3.0の 交響曲(シンフォニー) AKIBA.swift 第5回 @クラスメソッド株式会社 2016/09/20 Fumiya Sakai
  2. 2. 自己紹介と簡単な経歴など ✦ 今までの仕事履歴(本業) 石川県金沢市生まれ 本業はサーバーサイドのプログラマ ※Rails&PHP使い 26歳〜31歳: Webプログラマ(PHP & Rubyがキャリア長い) 23歳〜25歳: Webデザイナー兼ディレクター チャンスがあればiOSアプリ開発も絶賛やってみたい! 趣味:シルバーアクセサリー集め・スイーツ作り・アプリ開発 女子向け・グルメ・エンタメ関連のお仕事が多い Qiita : http://qiita.com/fumiyasac@github Github : https://github.com/fumiyasac ✦ 酒井文也(さかい ふみや) 東京(大塚)住まいの31歳 こんな格好を普段からしているので 遊び人に見られますがエンジニアです。 文系卒に思われますが 実は数学科で理系卒です。 めっちゃお酒好きそうに見えますが ビール苦手でお酒も超弱いです。 今でもたまにUIまわりとか触りたく なることがあったりなかったり 今年の4月からフリーランスです。 (割とお堅い感じの会社にいます) 最近のはまっている食べ物は カボチャと担々麺と甘栗です。 最近はSwift以外ではRailsやLaravel・CakePHP・Node.jsなんかも
  3. 3. これまでに作ったもの(ネイティブアプリ) ① 簡易家計簿アプリ「Coffre」 ② ゲームアプリ「10秒虫食い算」 ・カレンダーを自作しています ・シンプルなお小遣い帳感覚で支出管理できます ・全問正解者ほとんどいません… ・不定期ですがコラムも書いています ・サーバーサイドはRuby on Railsを使用 http://www.coffre.me/ ・デザインにもこだわってみました(特にグラフ) ・実はちょっとバグがあります。 ・問題は今後追加予定(現在110問収録) 個人的にはなりますが、他にもアプリ・Webサービスなど開発中です(2016年も宜しくお願いします) ・サイト等は次回のアップデートで公開予定 http://blog.just1factory.net/services/284 ・若干の中毒性を含みます
  4. 4. 人生で初めてiOSのライブラリを作りました 日本の祝祭日を計算で出してくれる ・カレンダーアプリ等での活用を想定 ・シルバーウィーク・ゴールデンウィークも対応 ・ハッピーマンデー法の施行も対応 ・春分の日・秋分の日にも対応 ・過去の祝祭日もおおむね考慮はしている 構想や基本実装は僕ですが、他に3名のContributorのお力添えがあり実運用できるレベルになりました! 職人の手作業で計算しております! & 現在XCode8とSwift2.3/3.0には誠意対応中です(><) ・HTTP(HTTPS)通信は不要 ★CalculateCalendarLogic ver0.0.2 【だが本業は今もサーバーサイドです】PHP(メインのframeworkはSymfony) & Ruby(Sinatraに近いもの?) ・Github: https://github.com/fumiyasac/handMadeCalendarAdvance ・実装解説: http://qiita.com/fumiyasac@github/items/33bfc07ad36dfffcdf8f ・Github: https://github.com/fumiyasac/handMadeCalendarOfSwift 手動での導入も可能!&日本語README完備!
  5. 5. ✦ 実装は十分に可能!そしてContainerViewをうまく活用すればね! Storyboardでも複雑なUIは作れるか? ContainerViewの特性を理解することで、Storyboardでもライブラリにもひけを取らない表現ができる DeNA中の人が解説する「マンガボックス」システム構成とiOSアプリの内部構成 開発規模やプロジェクト等によっては難しい部分もあるけど実運用の例もあるので活用の余地は十分ある! ★Storyboard + ContainerViewをフル活用するメリット ・Storyboardで画面遷移のイメージがしやすくなる&コードも追いやすくなる ・AutoLayout周りの設定がXcodeで行えるのでレイアウト関連のコード量の削減 ★もちろんデメリットの部分もある ・Gitでの差分確認のし辛さやUIソースの確認や管理が大変 ・大規模開発の場合ではソースが膨大になるため導入が難しい 【今回インスパイアされたスライドや記事】 ・画面の役割によってViewController自体を分割できる ソースコードやプロジェクト管理の観点からすると、規模によっては逆に大変になってしまう場合も https://codeiq.jp/magazine/2014/05/9946/ こちらも参考になります! だいすきStoryboard
  6. 6. ✦ ContainerViewの簡単な特徴とおさらい ContainerViewの基本のおさらい ContainerViewでの表現方法や特性と親子関係間でのメソッドの実行方法を知っておくとUI作成に役立つよ ★ContainerViewの特性をざっくりまとめ ★親子関係を意識するとお互いの処理のイメージがしやすくなる ・子から親のViewControllerのメソッドを呼び出す ViewController Container ※Embed Segue ViewController ・Embed Segueはつなぎ替えることも可 ・つながっているViewControllerへ値渡しも可 ・配置した時点で親子関係ができあがる 【主な特徴】 ・UIView型なのでTouchEvent/Gesture対応 ・子から親(逆もOK)のメソッドを実行可 //親のViewControllerのメソッドを実行する(子のViewController) let vc = self.parentViewController as! ParentViewController vc.doSomething() ・親から子のViewControllerのメソッドを呼び出す //子のViewControllerのメソッドを実行する(親のViewController)※indexは順番 let vc = self.chileViewControllers[index] as! ChildViewController vc.doSomething() ※Storyboardで配置した際は順番がわからない self.childViewControllers.forEach { vc in print(vc) } で実際に子のViewControllerの格納順を確認。 ※同様にクラスのプロパティを替えるのも可(Swift2.2)
  7. 7. ✦ ここで実際のアプリの動きの例を3つほど挙げてみましょう このアプリの動きはもしやこんな感じ?(1) 昨今のアプリではポピュラーかつ親しみのあるUIパターンなのでどんなアプリにも合わせやすい感じですね ★Case1. Creema ・一覧画面から詳細画面へ遷移するコンテンツとメニューが独立性を保った状態でそれぞれ振る舞う メインコンテンツが 右に動いてくれる Navigation Controller (Push Segue) メニューボタン 押下で表示 スワイプでコンテンツ が独立した状態で動く NavigationControllerの 挙動が担保された状態 ・ハンバーガーメニューを押すと隠れていたコンテンツが表示
  8. 8. ✦ ここで実際のアプリの動きの例を3つほど挙げてみましょう このアプリの動きはもしやこんな感じ?(2) 昨今のアプリではポピュラーかつ親しみのあるUIパターンなのでどんなアプリにも合わせやすい感じですね ★Case2. Retty ・一覧画面から詳細画面へ遷移するコンテンツとメニューが独立性を保った状態でそれぞれ振る舞う Navigation Controller (Push Segue) 右下「+」ボタン 押下で表示 NavigationControllerの 挙動が担保された状態 ・ハンバーガーメニューを押すと隠れていたコンテンツが表示(メニュー表示時はスワイプに追従) スワイプでコンテンツ が独立した状態で動く メインコンテンツが 右から出てくる (タッチイベント追従)
  9. 9. ✦ ここで実際のアプリの動きの例を3つほど挙げてみましょう このアプリの動きはもしやこんな感じ?(3) 昨今のアプリではポピュラーかつ親しみのあるUIパターンなのでどんなアプリにも合わせやすい感じですね ★Case3. クックパッド ・一覧画面から詳細画面へ遷移するコンテンツとメニューが独立性を保った状態でそれぞれ振る舞う Navigation Controller (Push Segue) ・ハンバーガーメニューを押すと隠れていたコンテンツが表示 メインコンテンツが 左に動いてくれる メニューボタン 押下で表示 スワイプでコンテンツ が独立した状態で動く NavigationControllerの 挙動が担保された状態
  10. 10. ✦ 前述の3アプリの感じに近い挙動をStoryboardで再現してみる Storyboard+ContainerViewで再現してみる Embed SegueやContainerViewの配置と制御とアニメーションやデザインとの組み合わせで様々な工夫が可能 ★僕なりの概要設計はこんな感じです ★NavigationControllerをはさんだViewControllerから土台のメソッドを呼ぶ場合 ・「ViewController(親) → NavigationController(子) → ContentListViewController(孫)」の図式 ※Embed Segue Navigation Controller ・土台部分とコンテンツ部分の制御の切り分け ・NavigationControllerをEmbed Segueで接続 ・コンテンツから土台の制御は親子関係を利用 【ポイント】 //親のViewControllerのメソッドを実行する(孫のViewController) let vc = self.parentViewController?.parentViewController as! ParentViewController vc.doSomething() 土台部分の ViewController メニュー部分の ViewController 一覧画面の ViewController 詳細画面の ViewController ※root view controller ※Push Segue … ContainerView(Menu) … ContainerView(Contents) *土台部分に配置するもの* ※(Swift2.2での記述になります) GestureRecognizer/TouchEvent で更に出現時の動きを表現可
  11. 11. ✦ Storyboardとの相性の良いライブラリの選定がポイント Storyboardベースの場合のライブラリ活用 ライブラリによってはアプリのUIがライブラリに強烈に依存する場合があるので設計時に注意すべし Swiftで便利なライブラリやUIパーツに工夫を凝らしてUIを彩るサンプル例(ライブラリ選定とベース作成) 機能や導入時の相性を確認した上であればライブラリを活用すればStoryboardベースであってもUIを彩れる ★CocoaPodsやCarthageで提供されているライブラリ導入時のポイント ・そのUI系ライブラリがStoryboardを使うことを考慮されているか ・導入や設定のガイドや実例が丁寧に解説されているか(Demoプロジェクトは必ず確認) ★画面全体の動きの制御と表現の部分での切り分けがしやすいような構成にする ・全体的な動きやメニュー周辺やコンテンツ表示エリアの大枠部分 → Storyboard + ContainerView ・コンテンツの要所で目立たせたい部分やポイントとなる部分 → 要所でライブラリを活用 【StoryboardとCocoaPodsライブラリの組み合わせ例】 ・修正やライブラリの仕様を崩さないカスタマイズの余地があるか ライブラリとの使い分けと依存関係や相性を調査した上で組み合わせればよりUIを彩ることもできる http://qiita.com/fumiyasac@github/items/96a588c4f7bfc901f729
  12. 12. ✦ 詳細に関しましてはサンプルと記事を交えて解説します 今回のサンプルと詳細解説はこちら 今回の解説の部分で「女子力」を使い切ってしまったので、サンプルはそれほど高くなくってすみません。 参考アプリ:RAKUNEW 詳細解説及びサンプルはこちら Github:https://github.com/fumiyasac/FundamentalContainerView 【サンプルはSwift2.2とSwift3.0両対応】 ※Swift3.0版はブランチ「feature/swift3」を参照 ・左右メニュー及びコンテンツ表示部分を ContainerViewを用いて分割 ・コンテンツ表示部分ではテーブルビューのヘッ  ダー部分やポップアップ部分でもポイントにな  る部分でContainerViewを活用 【追加ポイントなど】 今回のサンプルについて SwiftでContainerViewとStoryboardをフル活用して複雑なUIを実現する際の実装ポイントまとめ http://qiita.com/fumiyasac@github/items/17cbcffd90deee2cff43 JFYI: 本サンプルのSwift3.0対応時の解説はこちら http://qiita.com/fumiyasac@github/items/3218c35de5e59f3bfafa 前ページの解説に加えて追加したTIPS
  13. 13. ✦ 軽い気持ちで変換したらまあなかなか大変なことになりまして XCode8 + Swift3.0になってエラー続出! ★想像以上にかなりごっつく変化していた! レイアウトの設定を全く変えないでXCode8 + Swift3.0に取り組んでみましたので変更点をピックアップ! これぞまさに圧倒的破壊ッ!ヘヴィだぜッ! 実際の写真と今日の内容は、 全く関係ないんだからねッ!
  14. 14. ✦ CGRectMake / CGPointMake / CGSizeMakeの廃止 使い慣れたメソッドが使えなくなった よく使う&頻出のメソッドにも関わらずメソッド名だけでなく引数の型も若干変わっているメソッドに注意。 Swift3.0変更後の箇所をピックアップ ★CGRect / CGPoint / CGSizeへ生まれ変わります //サンプル内のTableViewHeaderViewControllerより抜粋 //UIScrollViewの表示エリアの大きさを設定 tableViewHeaderScrollView.frame = CGRect( x: 0, y :0, width: Int(DeviceSize.screenWidth()), height: 180 ) //UIPageControlの配置する位置を中心を基準に設定 tableViewHeaderPageControl.center = CGPoint( x: Int(DeviceSize.screenWidth() / 2), y: 150 ) //UIScrollViewの中のサイズを決定する tableViewHeaderScrollView.contentSize = CGSize( width: Int(DeviceSize.screenWidth()) * 3, height: 180 ) 設定する値の型もCGFloat型 → Int型へ変更 詳しい解説記事:(Swift3.0対応)ContainerViewとStoryboardをフル活用して複雑なUIを作るサンプルを Swift3.0へ書き直し対応した際のまとめ http://qiita.com/fumiyasac@github/items/3218c35de5e59f3bfafa
  15. 15. ✦ プロパティ名がわかりやすくなったところもあり プロパティ名の変更 プロパティ名称が変わって短くなったり、意味が推測しやすくなっているものもあるので確認しておこう。 Swift3.0変更後の箇所をピックアップ ★UIScrollViewのスクロールに関する設定 詳しい解説記事:(Swift3.0対応)ContainerViewとStoryboardをフル活用して複雑なUIを作るサンプルを Swift3.0へ書き直し対応した際のまとめ http://qiita.com/fumiyasac@github/items/3218c35de5e59f3bfafa //サンプル内のTableViewHeaderViewControllerより抜粋 //UIScrollViewの初期設定を行うプロパティ tableViewHeaderScrollView.isPagingEnabled = true tableViewHeaderScrollView.isScrollEnabled = false tableViewHeaderScrollView.isDirectionalLockEnabled = false is○○という名前になったのでちょっとわかりやすい Swift3.0変更後の箇所をピックアップ ★子のViewControllerから親のメソッドを呼び出す処理 //サンプル内のContentListViewHeaderViewControllerより抜粋 //コンテンツ部分のContainerViewを動かしてメニューを出す let viewController = self.parent?.parent as! ViewController viewController.handleMainContentsContainerState(status: MainContentsStatus.LeftMenuOpened) parentViewController → parentとなってシンプルに メソッドの第1引数の引数名は省略不可になった
  16. 16. ✦ アニメーション関連やaddTargetメソッドのselector:の書き方 書き方やメソッド名がガラッと変わった よく使う&頻出のメソッドなのにガラリと変わってしまった部分はAppleの公式ドキュメント等でチェック! ★アニメーションの書き方はSwift2.2から変わったポピュラーな例 Swift3.0変更後の箇所をピックアップ //サンプル内のListDetailViewControllerより抜粋 //サブコンテンツのポップアップの開閉アニメーション部分 //ボトムのポップアップを開く func openBottomPopup() { topPopupConstraint.constant = 17 bottomPopupConstraint.constant = 0 UIView.animate(withDuration: 0.26, delay: 0, options: UIViewAnimationOptions.curveEaseOut, animations: //変更したAutoLayoutのConstant値を適用する { self.view.layoutIfNeeded() }, completion: { finished in } ) } メソッドの第1引数の引数名は省略不可になった 詳しい解説記事:(Swift3.0対応)ContainerViewとStoryboardをフル活用して複雑なUIを作るサンプルを Swift3.0へ書き直し対応した際のまとめ http://qiita.com/fumiyasac@github/items/3218c35de5e59f3bfafa animateWithDuration → animateへ変更 options: に指定するenumの先頭は大文字から小文字
  17. 17. ✦ 複雑なUIをContainerView + Storyboardをフル活用は侮れない! 今回のまとめ ご清聴ありがとうございました!またこのような機会があった際には是非ともよろしくお願い致します! ★複数の選択肢やライブラリの検討 管理面でのデメリットはあれども、画面遷移の設計のしやすさやViewControllerの分割等は強力 ★ライブラリを使う際には「動くこと + α」の精査や実装デモ等の把握を Storyboardとの相性はもちろんのこと、ライブラリの保守状況や使用時のTIPSも把握しておく ★Swift3.0対応時にはその変更点に気をつける UIまわりのクラスやメソッドに関しても大幅な変更があったので実装時には十分に注意を ★自分ルール 【良いアウトプットのために】 発表・登壇時はこの中のいずれか2つを 絶対に準備するルールを設けています!

×