目次

はじめに

動作環境及びバージョン
サンプルコードに関して
誤表記などに関するお問い合わせに関して
サンプルのURLと見た目
免責事項
表記関係について
底本について

第1章 サイドナビゲーション型のUI

1.1 ContainerViewについての確認
1.2 ContainerViewの活用ポイント
1.3 スライドするメニュー表示の概要と実装
1.4 StoryBoard構成とコードの解説
1.5 サイドナビゲーション実装における別解

第2章 写真を拡大する画面遷移UI

2.1 View実装に関するTips集
2.2 使用したライブラリーのご紹介
2.3 カスタムトランジションの基本実装
2.4 画面遷移前の一覧画面の実装
2.5 画面遷移後の詳細画面の実装
2.6 本サンプルにおける画面遷移表現のまとめ

第3章 Tinder風のUI

3.1 実装する上でのポイント
3.2 処理の橋渡しを行うプロトコル実装
3.3 画面に追加した際の演出
3.4 カード状のViewとUIPanGestureRecognizer
3.5 UIViewControllerとの連携部分の実装
3.6 UIScrollViewを利用した画像表示の実装

第4章 入力フォームの実装例

4.1 入力に関するView部品の実装
4.2 使用したライブラリーのご紹介
4.3 UITableViewを利用した表現Tipsの紹介
4.4 入力フォームの部分に関する画面実装

あとがき

はじめに

 本書を手に取って頂きましてありがとうございます。筆者は現在、主にiOSアプリ開発(使用言語はSwift/Objective-C)を行っています。特にその中でも、アプリのUI実装に関する部分に携わる多くの機会がありました。

 また業務以外の場所でも、登壇などでUI実装に関することをお話したり、TIPSを投稿する等の活動をこれまでも行ってきました。その他勉強会など同業のエンジニアの方々との交流の中で、「Web制作ではUI実装に関する紹介書籍があるのなら、iOSアプリ開発においてもUI実装に関する書籍の需要はあるのでは?」と感じることがありました。そもそも筆者は、キャリアのはじめがデザイナーから始まり、そこからWebエンジニアを経てモバイルアプリエンジニアになった経緯もあったので、今でもUI実装に関する部分に一番関心をもっています。

 iOSアプリのUIに関しては、「Human Interface Guidelines」1というiOSアプリ開発において極めて大切なドキュメントがあります。しかし、アプリ個々のUIを見ると、OSのバージョンアップやトレンドの変化はもちろん、プロダクトのデザインによってそれぞれの構成や実装方法、選択しているアーキテクチャーによっても変わります。

 この点を踏まえ、本書ではいくつかのまとまったサンプル実装を例に、UI構築をする上で重要な実装ポイントやアイデアを紹介します。一手間を加えた実装を加えたり、サードパーティーのライブラリーを上手に活用することで、既存のUIに素敵な彩りを添えることが実現可能なものがあります。本書で紹介している例は、筆者が業務でのアプリ開発で利用したTIPSや勉強会での登壇の際に作成したサンプルで利用したものを掲載しています。

 基本的な理解ができるようになり、これからiOSアプリを本格的に開発していこうと考えている方や、UI実装や表現に関する部分にさらなる磨きをかけていきたい方にとって、本書が少しでも役立つことができれば幸いです。筆者自身も現状に甘んじることなく、自分の開発技術や表現の幅を広げる努力を惜しまずに歩み続けていこうと思います。

動作環境及びバージョン

 本書の内容及び紹介しているサンプルのコードに使用したバージョンにつきましては、次の通りになります。またXcodeやSwiftのバージョンが上がった際には、Githubリポジトリー等でお伝えしていく予定です。

 掲載しているサンプルに関しては、2018.11.25(初版改訂時)のものになります。以前の2018.08.04(初版執筆時)のコードについてもリポジトリー内に残しております。

 ・macOS Mojave 10.14

 ・Xcode 10.1

 ・Swift 4.2

 ・CocoaPods 1.5.3

必要な前提知識

 ・XcodeやSwiftに関する基本的な知識

 ・AutoLayoutやStoryboard・Xibに関する基本的な知識

サンプルコードに関して

 書籍で紹介しているサンプルコードは次のリポジトリーで公開しています。

 ・Github: https://github.com/fumiyasac/ios_ui_recipe_showcase/tree/convert_xcode10

 また、使用した写真素材は「写真AC(https://www.photo-ac.com/)」によるものです。

 ※ masterブランチに格納しているものは、Xcode9.4.1 & Swift4.1で実装したものになります。

誤表記などに関するお問い合わせに関して

 本書で掲載している内容につきましては、誤りがないように細心の注意を払っておりますが、もし訂正等がございましたら次のメールアドレスやGithubのissue、Twitter等を通してご一報頂けますと幸いです。

 ・Mail: just1factory@gmail.com

 ・Twitter: https://twitter.com/YuxBeta

サンプルのURLと見た目

第1章

 ・サンプル実装の難易度: ★★★★☆☆☆☆☆☆

  ─サンプルプロジェクト名: MenuContentsExample

第2章

 ・サンプル実装の難易度: ★★★★★★★★★☆

  ─サンプルプロジェクト名: InteractiveUIExample

第3章

 ・サンプル実装の難易度: ★★★★★★★☆☆☆

  ─サンプルプロジェクト名: LikeTinderExample





第4章

 ・サンプル実装の難易度: ★★★★★★☆☆☆☆

  ─サンプルプロジェクト名: ReservationFormExample

免責事項

 本書に記載された内容は、情報の提供のみを目的としています。したがって、本書を用いた開発、製作、運用は、必ずご自身の責任と判断によって行ってください。これらの情報による開発、製作、運用の結果について、著者はいかなる責任も負いません。

表記関係について

 本書に記載されている会社名、製品名などは、一般に各社の登録商標または商標、商品名です。会社名、製品名については、本文中では©、®、™マークなどは表示していません。

底本について

 本書籍は、技術系同人誌即売会「技術書典5」で頒布されたものを底本としています。

第1章 サイドナビゲーション型のUI

この章では、複数のContainerViewを組み合わせて、スライドメニューのようなViewとコンテンツの切り替えを行う部分に関して解説します。メニューの開閉や現在表示している画面からの切り替えに関する部分は、コンテンツの量が多いアプリでよく目にする部分ですが、いざ自前で実装する時には大変な部分のひとつです。

1.1 ContainerViewについての確認

 ContainerViewは、その名の通り「ViewControllerを表示するための入れ物となるView」です。

 InterfaceBuilderからContainerと書いてあるView要素を引っ張って来たときに、UIViewControllerが「Embed Segue」でつながれたViewが表示されます。ここで大事のは、Embed Segueで繋がっているViewControllerと、ContainerViewを配置したViewControllerは親子関係を持つことです。

 この親子関係をうまく活用することで、任意のViewController内で親子関係を持つ別のViewControllerを表示したり、親子関係を利用した処理を組み立てることができます(※Notificationを活用するという方針も考えられますが、画面遷移やアプリの動き方が複雑な場合、実装時の考慮漏れが起きやすくなります)。

 もちろん、ContainerViewだけをあらかじめ配置し、その中に表示したいViewControllerをコードやInterfaceBuilderから接続したり、Segueの名前からContainerViewに繋がるViewControllerのインスタンスを取得することもできます。そのためStoryboardと相性がよく、画面遷移を直感的に作成できたり、それぞれの画面ごとにViewControllerを分割・整理できる点は大きなメリットです。

 ContainerViewの特性を活用したUIを考えていく上のポイントは次の3点です。

 1.全体的な画面遷移やContaierViewで、Embed Segueで紐付けされているViewControllerの関係

 2.異なるController間でプロトコルを用いて処理や値を橋渡しをする部分

 3.親ないしは子のViewControllerのインスタンスを活用する部分

 これらに留意した上で実装を行えば、良い実装になるでしょう。

1.2 ContainerViewの活用ポイント

 前述したとおり、ContainerViewをInterfaceBuilderで表示した際には、すでにViewControllerがつながった状態で表示されます。ここからは、ContainerViewの性質に関するポイントをいくつか紹介します。

 図1.1は、InterfaceBuilderでの見え方です。今回紹介するサンプルでは、LayoutをStoryboardないしはXibを活用しているためにGUIとの連携している部分が多くなっています。サンプルを見て、設定している場所を確認しながら進めばより理解が深まるでしょう。

図1.1: ContainerViewの見え方

 またEmbed Segueについては普通のViewControllerだけでなく、NavigationControllerやStoryboard Referenceとつなぐことも可能です。作成したいiOSアプリの構造やUIに合わせて活用してみてください。

 次にContainerViewを取り扱う上でポイントとなる、配置されているViewControllerとの親子関係について解説します。親子間での処理の受け渡しについては、次のふたつの方針が考えられます。

 1.親ないしは子のViewControllerのインスタンスを作成して、任意の処理を実行する

 2.親ないしは子のViewControllerにプロトコルを定義して、任意の処理を実行する

 これらを実行したい処理に応じて使い分けますが、ここでは1.の手法を紹介します。

 リスト1.1は、ContainerViewを配置したViewControllerで、親子関係を利用して子のViewControllerで親のクラスのインスタンスを取得するコードの例です。

リスト1.1: 子のViewControllerから親側の処理を実行する

 1: // ※ 任意の親のさらに親をたどる場合は self.parent?.parent ... となる
 2: if let vc = self.parent {
 3:     let parentViewController = vc as! ParentViewController
 4:     parentViewController.doSomething()
 5: }

 逆にリスト1.2は、親のViewControllerから子のViewControllerで親のクラスのインスタンスを取得するコードの例です。

リスト1.2: 親のViewControllerから子側の処理を実行する

 1: // ※ 子のViewController達は[ViewController]型で格納されているので、indexはその順番の値
 2: let childViewController = self.childViewControllers[index] as! ChildViewController
 3: childViewController.doSomething()
 4:
 5: // ※ 次のようなログを出力して該当のインデックス値を調べるのも方法の一つ
 6: self.childViewControllers.forEach { vc in
 7:     print(vc)
 8: }

リスト1.3: デバッグコンソール出力結果

 1: <プロジェクト名.indexが0のコントローラー名: xxxx…>
 2: <プロジェクト名.indexが1のコントローラー名: xxxx…>
 3: <プロジェクト名.indexが2のコントローラー名: xxxx…>
 4: ...

 配置した任意のContainerViewに、Enbed Segueで接続されているViewControllerのインスタンスをSegue Identifierから取得する方法も紹介します。ここでは、従来のSegueでの画面遷移に置いて遷移先に何かしら値を引き渡す際と同様に、リスト1.4」の様にprepareメソッドを利用します。

リスト1.4: Embed Segue名からつないでいるViewControllerを取得

 1: // 接続されている「Segue Identifier」から該当のViewControllerを取得します
 2: // MEMO: SideNavigationViewControllerの名前をこのようにする
 3: // →「Embed Segue: connectSideNavigationContainer」
 4: override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
 5:     if segue.identifier == "connectSideNavigationContainer" {
 6:         let sideNavigationViewController
 7:             = segue.destination as! SideNavigationViewController
 8:         sideNavigationViewController.delegate = self
 9:     }
10: }

 InterfaceBuilderとコードの合わせ技でのContainerViewを活用したUI実装は、アプリレイアウトの基盤部分に関わるものになる事もあります。実装をマスターしておくと助かる事が多いのではないでしょうか。

1.3 スライドするメニュー表示の概要と実装

 今回のサンプルでは、まずナビゲーションバーの左上部にあるボタンをタップする、ないしは画面の左端からドラッグした際に、コンテンツの下部に隠れているサイドナビゲーションを表示します。同時に、メインのコンテンツ表示部分をタップできなくして、逆向きにドラッグするか移動したコンテンツ表示部分に触れるとサイドナビゲーションを隠します。この一連の動きをContainerViewを用いて実装しました。

 様々なアプリでよく見かける、今や定番となっている動きですが、今回はこの動きをライブラリーに任せてしまうのではなく、GestureRecognizerやTouchEventを用いて実現する事例を解説します。

図1.2: サンプルのデザイン

 今回の実装にあたって、ContainerViewの特性やプロトコルを活用することで、単純に適切なタイミングでのコンテンツ切り替えを動作させるだけでなく、より一層動きに彩りを添えるためにアニメーションも加えました。

 この手のGestureRecognizerやTouchEventを伴い、画面の状態が意図通りのタイミングで処理がなされているかを検証する際は、正常な動作だけではなく、次のような意図しない動作や行動に関する検証も忘れないようにしてください。

 ・例1. 1本指でドラッグするのが期待される動作だが、2本指での操作でも不具合がないか

 ・例2. 開く途中の状態で、さらにもう一方の手でドラッグをした際に不具合がないか

 実際に触ってのUI検証はなかなか面倒ですが、これを怠ることで意図しない動作をした際にフリーズしたり、最悪の場合クラッシュを引き起こしやすいので注意しましょう。

試し読みはここまでです。
この続きは、製品版でお楽しみください。