iOS Viewプログラミングガイド

iOS View
プログラミングガイド
目次
ウインドウとビューの概要 7
はじめに 7
ビューによりアプリケーションの視覚的なコンテンツを管理 7
ウインドウによりビューの表示を統合 8
アニメーションによりインターフェイスの変更について目に見えるフィードバックをユーザに提
供 8
Interface Builderの役割 8
関連項目 9
ビューとウインドウのアーキテクチャ 10
ビューのアーキテクチャの基本 10
ビュー階層とサブビューの管理 11
ビューの描画サイクル 12
コンテンツモード 13
引き延ばし可能なビュー 13
組み込みアニメーションのサポート 14
ビューのジオメトリと座標系 16
frame、bounds、およびcenterプロパティの関係 16
座標系の変換 17
ポイントとピクセル 19
実行時のビューの相互作用モデル 20
ビューを効果的に使用するためのヒント 23
ビューには必ずしも対応するビューコントローラがあるとは限らない 23
カスタム描画を最小限にする 23
コンテンツモードを利用する 23
可能な場合は常にビューを不透明として宣言する 24
スクロール時のビューの描画動作を調整する 24
サブビューの埋め込みでコントロールをカスタマイズしない 24
ウインドウ 25
ウインドウの使用を伴うタスク 25
ウインドウの作成と設定 26
Interface Builderでのウインドウの作成 26
プログラムによるウインドウの作成 27
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
2
目次
ウインドウへのコンテンツの追加 28
ウインドウレベルの変更 29
ウインドウの変更の監視 29
外部ディスプレイでのコンテンツの表示 30
画面の接続および接続解除に関する通知の処理 31
外部ディスプレイ用のウインドウの設定 33
外部ディスプレイの画面モードの設定 35
ビュー 36
ビューオブジェクトの作成と設定 36
Interface Builderを使用したビューオブジェクトの作成 36
プログラムによるビューオブジェクトの作成 37
ビューのプロパティの設定 38
タグによるビューの識別 40
ビュー階層の作成と管理 40
サブビューの追加と削除 41
ビューの非表示 44
ビュー階層でのビューの検索 45
ビューの平行移動、拡大縮小、回転 45
ビュー階層での座標の変換 46
実行時のビューのサイズと位置の調整 47
レイアウト変更への備え 47
自動サイズ変更規則を使用した自動的なレイアウト変更の処理 48
手動によるビューのレイアウトの調整 49
実行時のビューの変更 50
Core Animationレイヤとのやり取り 51
ビューに関連付けられたレイヤクラスの変更 52
ビューへのレイヤオブジェクトの埋め込み 52
カスタムビューの定義 54
カスタムビューを実装する際のチェックリスト 54
カスタムビューの初期化 55
描画コードの実装 56
イベントへの応答 57
ビューを使用した後のクリーンアップ 59
アニメーション 60
アニメーション化の対象 60
ビューのプロパティに対する変更のアニメーション化 62
ブロックベースのメソッドを使用したアニメーションの開始 62
begin/commitメソッドを使用したアニメーションの開始 65
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
3
目次
アニメーションブロックのネスト 69
逆再生を行うアニメーションの実装 70
ビュー間のアニメーション化されたトランジションの作成 71
ビューのサブビューの変更 71
別のビューへの置き換え 73
複数のアニメーションのリンク 74
ビューとレイヤの変更の同時アニメーション化 75
書類の改訂履歴 78
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
4
図、表、リスト
ビューとウインドウのアーキテクチャ 10
図 1-1
図 1-2
図 1-3
図 1-4
図 1-5
図 1-6
図 1-7
表 1-1
サンプルアプリケーションのビューのアーキテクチャ 11
コンテンツモードの比較 13
ボタンの背景の引き延ばし 14
UIKitの座標系の向き 16
ビューのフレームと境界の関係 17
ビューとそのコンテンツの回転 19
UIKitとビューオブジェクトとの対話 20
iOSベースのデバイスの画面サイズ 19
ウインドウ 25
リスト 2-1
リスト 2-2
リスト 2-3
画面の接続および接続解除に関する通知の登録 31
接続および接続解除に関する通知の処理 32
外部ディスプレイ用のウインドウの設定 33
ビュー 36
図 3-1
図 3-2
図 3-3
図 3-4
表 3-1
表 3-2
リスト 3-1
リスト 3-2
リスト 3-3
リスト 3-4
リスト 3-5
リスト 3-6
「時計(Clock)」アプリケーションにおけるビューの階層化 41
ビューの45度回転 46
回転したビューの値の変換 47
ビューの自動サイズ変更マスク定数 49
主なビューのプロパティの使用方法 38
自動サイズ変更マスク定数 48
ウインドウへのビューの追加 42
既存のビュー階層へのビューの追加 42
ビューへのカスタムレイヤの追加 53
ビューのサブクラスの初期化 55
描画メソッド 57
deallocメソッドの実装 59
アニメーション 60
表 4-1
表 4-2
リスト 4-1
リスト 4-2
アニメーション化可能なUIViewのプロパティ 60
アニメーションブロックを設定するメソッド 66
簡単なブロックベースのアニメーションの実行 63
カスタムオプションを使用したアニメーションブロックの作成 64
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
5
図、表、リスト
リスト 4-3
リスト 4-4
リスト 4-5
リスト 4-6
リスト 4-7
リスト 4-8
リスト 4-9
簡単なbegin/commitアニメーションの実行 65
begin/commitメソッドを使用したアニメーションパラメータの設定 67
設定の異なるアニメーションのネスト 69
既存のテキストビューと空のテキストビューの切り替え 72
begin/commitメソッドを使用したサブビューの変更 73
ビューコントローラの2つのビューの切り替え 73
ビューとレイヤのアニメーションの混在 75
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
6
ウインドウとビューの概要
iOSでは、ウインドウとビューを使用してアプリケーションのコンテンツを画面に表示します。ウイ
ンドウ自体は表示するコンテンツを持ちませんが、アプリケーションのビューのための基本的なコン
テナを提供します。ビューは、コンテンツを表示するウインドウの領域を定義します。たとえば、イ
メージ、テキスト、図形、またはこれらの組み合わせを表示するビューがあります。また、ビューを
使用してほかのビューを組み合わせたり、管理することもできます。
はじめに
すべてのアプリケーションには、コンテンツを表示するために、少なくとも1つのウインドウと1つの
ビューがあります。UIKitやその他のシステムフレームワークには、コンテンツを表示するために使用
できる定義済みのビューが用意されています。これらのビューは、簡単なボタンやテキストラベルか
ら、テーブルビュー、ピッカービュ、スクロールビューなどのより複雑なビューへと多岐にわたって
います。必要な処理が定義済みのビューで提供されていない場合は、カスタムビューを定義して、描
画やイベント処理を独自に管理することもできます。
ビューによりアプリケーションの視覚的なコンテンツを管理
ビューは、UIViewクラス(または、そのサブクラス)のインスタンスであり、アプリケーションウ
インドウ内の矩形の領域を管理します。ビューは、コンテンツの描画、マルチタッチイベントの処
理、およびサブビューのレイアウトの管理を行います。描画には、ビューの矩形領域に図形、イメー
ジ、およびテキストを描画するために、Core Graphics、OpenGL ES、UIKitなどのグラフィックステク
ノロジーが使用されます。ビューは、ジェスチャリコグナイザを使用するかタッチイベントを直接処
理することで、矩形領域のタッチイベントに応答します。ビュー階層では、親ビューが子ビューの配
置とサイズ設定を行い、これらの処理を動的に実行できます。子ビューを動的に変更できるため、
ビューはインターフェイスの回転やアニメーションなどの状況の変化に対応することができます。
ビューは、ユーザインターフェイスを構築するための基本単位と見なすことができます。1つのビュー
ですべてのコンテンツを表示するのではなく、通常は複数のビューを使用してビュー階層を構築しま
す。階層内の各ビューは、ユーザインターフェイスの特定の部分を表し、通常はコンテンツのタイプ
に合わせて最適化されます。たとえば、UIKitにはイメージ、テキスト、その他のタイプのコンテンツ
の表示に特化したビューがあります。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
7
ウインドウとビューの概要
はじめに
関連する章: “ビューとウインドウのアーキテクチャ” (10 ページ), “ビュー” (36 ページ)
ウインドウによりビューの表示を統合
ウインドウはUIWindowクラスのインスタンスで、アプリケーションのユーザインターフェイスの表
示を総合的に処理します。ウインドウは、ビュー(および所有するビューコントローラ)と連携し
て、表示しているビュー階層とのやり取りやビュー階層の変更を管理します。ほとんどの場合、アプ
リケーションのウインドウが変更されることはありません。ウインドウが作成されたら、ウインドウ
に表示されるビューのみを変更します。各アプリケーションにはウインドウが少なくとも1つあり、
デバイスのメイン画面でアプリケーションのユーザインターフェイスを表示するために使用されま
す。デバイスに外部ディスプレイが接続される場合は、外部ディスプレイの画面にコンテンツを表示
するために、アプリケーションが2つ目のウインドウを作成することもあります。
関連する章: “ウインドウ” (25 ページ)
アニメーションによりインターフェイスの変更について目に見えるフィー
ドバックをユーザに提供
アニメーションは、ビュー階層に対する変更について目に見えるフィードバックをユーザに提供しま
す。システムには、モーダルビューの表示や別のグループのビューへのトランジションに対して標準
のアニメーションが定義されています。ただし、ビューの多くの属性は直接アニメーション化するこ
ともできます。たとえば、ビューの透明度、画面上の位置、サイズ、背景色、その他の属性などを変
更できます。ビューの基礎となるCore Animationレイヤオブジェクトを直接操作すると、その他の多
くのアニメーションも実行できます。
関連する章: “アニメーション” (60 ページ)
Interface Builderの役割
Interface Builderは、アプリケーションのウインドウとビューを視覚的に構築および設定できるアプリ
ケーションです。Interface Builderを使用して、ビューを組み合わせてnibファイルに配置します。この
ファイルは、ビューとその他のオブジェクトの状態と設定を格納するリソースファイルです。実行時
にnibファイルをロードすると、ファイル内のオブジェクトが実際のオブジェクトに再構成され、コー
ド内のプログラムによってオブジェクトを操作できるようになります。
Interface Builderにより、アプリケーションのユーザインターフェイスを作成するために必要な作業は
大幅に簡素化されます。Interface BuilderとnibファイルのサポートはiOSに統合されているため、アプ
リケーションの設計にnibファイルを組み込むための労力はほとんど必要ありません。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
8
ウインドウとビューの概要
関連項目
Interface Builderの使用方法については、『Interface Builder User Guide 』を参照してください。ビューコ
ントローラがビューを含むnibファイルを管理する方法については、『View Controller Programming
Guide for iOS 』の「Creating Custom Content View Controllers」を参照してください。
関連項目
ビューは高度で柔軟なオブジェクトであるため、すべての動作を1つのドキュメントだけで説明する
ことはできませんが、ほかのドキュメントを利用すれば、ビューおよびユーザインターフェイスの管
理をさまざまな面から総合的に学習できます。
●
●
●
●
ビューコントローラは、アプリケーションのビューを管理する上で重要です。ビューコントロー
ラは1つのビュー階層内のすべてのビューを管理し、これらのビューを画面に簡単に表示できる
ようにします。ビューコントローラとその役割の詳細については、『View Controller Programming
Guide for iOS 』を参照してください。
アプリケーションのジェスチャとタッチイベントは、主にビューによって受信されます。ジェス
チャリコグナイザの使用方法とタッチイベントを直接処理する方法については、『EventHandling
Guide for iOS 』を参照してください。
カスタムビューでは、コンテンツをレンダリングするために、利用可能な描画テクノロジーを使
用する必要があります。描画テクノロジーを使用してビュー内で描画する方法については、
『Drawing and Printing Guide for iOS 』を参照してください。
標準ビューのアニメーションが十分でない場合は、Core Animationを使用できます。Core Animation
を使用してアニメーションを実装する方法については、『Core Animation Programming Guide 』を
参照してください。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
9
ビューとウインドウのアーキテクチャ
ビューとウインドウはアプリケーションのユーザインターフェイスを表示し、インターフェイスとの
やり取りを処理します。UIKitおよびその他のシステムフレームワークには、ほぼそのまま使用できる
多数のビューが用意されています。標準のビューとは異なる方法でコンテンツを表示する必要がある
場合は、カスタムビューを定義することもできます。
システムビューを使用する場合、または独自のカスタムビューを作成する場合のどちらでも、UIView
とUIWindowクラスで提供されているインフラストラクチャを理解する必要があります。これらのク
ラスは、ビューのレイアウトと表示を管理する高度な機能を提供します。これらの機能の動作を理解
することは、アプリケーションで変更が発生したときにビューを適切に動作させるために重要です。
ビューのアーキテクチャの基本
視覚的な効果を伴う処理のほとんどは、ビューオブジェクト(UIViewクラスのインスタンス)によっ
て行われます。ビューオブジェクトは画面上の矩形領域を定義し、その領域における描画とタッチイ
ベントを処理します。ビューはほかのビューの親になることも可能で、これらの子ビューの配置とサ
イズを調整できます。これらのビュー間の関係を管理する処理のほとんどはUIViewクラスによって
行われますが、必要に応じてデフォルトの動作をカスタマイズすることもできます。
ビューはCore Animationレイヤと連携して、ビューのコンテンツのレンダリングとアニメーション化
を処理します。UIKitの各ビューには下位レベルのレイヤオブジェクト(通常は、CALayerクラスのイ
ンスタンス)があり、ビューのバッキングストアの管理と、ビューに関連するアニメーションの処理
を行います。ほとんどの操作は、UIViewインターフェイスを通して実行します。ただし、ビューの
レンダリングやアニメーションの動作をより細かく制御する必要がある場合は、レイヤ通じて操作で
きます。
ビューとレイヤの関係は、例を見ると理解しやすくなります。図 1-1は、『ViewTransitions 』のサンプ
ルアプリケーションのビューのアーキテクチャと、基礎となるCore Animationレイヤとの関係を示し
ています。アプリケーションのビューには、ウインドウ(ビューでもあります)、コンテナビューと
して動作する汎用のUIViewオブジェクト、画像ビュー、コントロールを表示するためのツールバー、
およびバー上に表示するボタン(それ自体はビューではありませんが、ビューを内部的に管理しま
す)が含まれます(実際の『ViewTransitions 』のサンプルアプリケーションには、トランジションを
実装するために使用する別の画像ビューも含まれています。説明を簡単にするため、また通常この
ビューは表示されないため、図 1-1には含まれていません)。すべてのビューには対応するレイヤオ
ブジェクトがあり、ビューのlayerプロパティからアクセスできます(バー上に表示するボタンは
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
10
ビューとウインドウのアーキテクチャ
ビューのアーキテクチャの基本
ビューでないため、このレイヤには直接アクセスできません)。これらのレイヤオブジェクトの下位
レベルには、Core Animationレンダリングオブジェクトがあり、最下層には画面上の実際のビットを
管理するためのハードウェアバッファがあります。
図 1-1
サンプルアプリケーションのビューのアーキテクチャ
Core Animationレイヤオブジェクトの使用は、パフォーマンスの面で重要な意味があります。ビュー
オブジェクトの実際の描画コードは必要最小限で呼び出され、呼び出された場合は結果がCore Animation
によってキャッシュされ、可能な限り再利用されます。すでにレンダリングされたコンテンツを再利
用することで、ビューの更新で通常必要とされる負荷の大きい描画サイクルを避けることができま
す。このコンテンツの再利用はアニメーションにおいて特に重要です。既存のコンテンツを操作する
ことで、新しいコンテンツを作成するよりも負荷を小さくすることができます。
ビュー階層とサブビューの管理
ビューは独自のコンテンツを提供するほかに、ほかのビューのコンテナとしても機能します。ビュー
にほかのビューが含まれる場合、これらの2つのビュー間には親子関係が作成されます。この関係に
おいて、子ビューはサブビュー、親ビューはスーパービューとも呼ばれます。このタイプの関係を作
成することは、アプリケーションの視覚的な外観とその動作の両方に影響します。
視覚的な面では、サブビューのコンテンツは親ビューのコンテンツの全体または一部を覆います。サ
ブビューが完全に不透明な場合、サブビューが占める領域は親ビューの対応する領域を完全に覆い隠
します。サブビューが半透明の場合は、2つのビューのコンテンツが画面に表示される前にブレンド
されます。各スーパービューはサブビューを順序付けされた配列に格納し、配列内の順序も各サブ
ビューの表示に影響します。同じ親に属するサブビューが重なり合っている場合は、最後に追加され
たビュー(または、サブビュー配列の末尾に移動されたビュー)がほかのビューの上に表示されま
す。
スーパービューとサブビューの関係は、いくつかのビューの動作にも影響します。親ビューのサイズ
を変更すると、各サブビューのサイズと位置も波及的に変更されます。親ビューのサイズを変更する
と、ビューを適切に設定することで、各サブビューのサイズ変更の動作を制御できます。サブビュー
に影響するその他の変更には、スーパービューの非表示、スーパービューのアルファ(透明度)の変
更、スーパービューの座標系への数学的変換の適用などがあります。
ビュー階層におけるビューの配置は、アプリケーションがどのようにイベントに応答するかも決定し
ます。特定のビュー内でタッチが発生すると、システムは、イベントオブジェクトをタッチ情報と共
に直接ビューに送付して処理します。ただし、ビューが特定のタッチイベントを処理しない場合、
ビューはそのイベントをスーパービューに渡すことがあります。スーパービューがそのイベントを処
理しない場合、イベントオブジェクトはレスポンダチェーンに沿ってさらにそのスーパービューに渡
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
11
ビューとウインドウのアーキテクチャ
ビューのアーキテクチャの基本
されます。特定のビューが、イベントオブジェクトをビューコントローラなどの中間レスポンダオブ
ジェクトに渡す場合もあります。いずれのオブジェクトもイベントを処理しない場合、イベントは最
終的にアプリケーションオブジェクトまで到達し、一般的にここで破棄されます。
ビュー階層の作成方法については、“ビュー階層の作成と管理” (40 ページ)を参照してください。
ビューの描画サイクル
UIViewクラスは、オンデマンドの描画モデルを使用してコンテンツを表示します。ビューが最初に
画面に表示されるとき、システムはビューにコンテンツを描画するよう要求します。システムは、こ
のコンテンツのスナップショットをキャプチャし、ビューのビジュアル表現としてそのスナップショッ
トを使用します。ビューのコンテンツを変更しない限り、ビューの描画コードが再度呼び出されるこ
とはありません。ビューに関するほとんどの操作で、スナップショットイメージが再利用されます。
コンテンツを変更する場合は、ビューが変更されたことをシステムに通知します。ビューは、ビュー
を描画するプロセスと新しい結果のスナップショットをキャプチャするプロセスを繰り返します。
ビューのコンテンツを変更するときは、これらの変更を直接再描画しません。代わりに、
setNeedsDisplayメソッドまたはsetNeedsDisplayInRect:メソッドのいずれかを使用して、ビュー
を無効にします。これらのメソッドは、ビューのコンテンツが変更され、次回再描画する必要がある
ことをシステムに示します。システムは現在の実行ループが終了するのを待ってから、描画操作を開
始します。この遅延により、複数のビューの無効化、階層に対するビューの追加または削除、ビュー
の非表示、ビューのサイズ変更、およびビューの再配置を一度に実行することができます。続いて、
行った変更がすべて同時に反映されます。
注意: ビューのジオメトリを変更しても、システムはビューのコンテンツを自動では再描画
しません。ビューのcontentModeプロパティで、ビューのジオメトリに対する変更を解釈す
る方法が決定されます。ほとんどのコンテンツモードは、既存のスナップショットをビュー
の境界内で引き延ばすか再配置し、新しく作成しません。ビューの描画サイクルに対するコ
ンテンツモードの影響については、“コンテンツモード” (13 ページ)を参照してください。
ビューのコンテンツをレンダリングするときの実際の描画プロセスは、ビューとその設定によって異
なります。一般的に、システムビューはプライベートな描画メソッドを実装してコンテンツをレンダ
リングします多くの場合、同様のシステムビューでは、ビューの実際の外観を設定するためのイン
ターフェイスが公開されています。カスタムUIViewサブクラスでは、ビューのdrawRect:メソッドを
オーバーライドし、そのメソッドを使用してビューのコンテンツを描画するのが一般的です。ビュー
のコンテンツを提供する方法としては、下位レベルのレイヤのコンテンツを直接設定するなどの方法
もありますが、drawRect:メソッドをオーバーライドする手法が最も一般的です。
カスタムビューのコンテンツを描画する方法については、“描画コードの実装” (56 ページ)を参照
してください。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
12
ビューとウインドウのアーキテクチャ
ビューのアーキテクチャの基本
コンテンツモード
各ビューにはコンテンツモードがあります。このモードでは、ビューのジオメトリに対する変更に応
じてビューがコンテンツを再利用する方法と、ビューがコンテンツを再利用するかどうかを制御しま
す。ビューが最初に表示されるとき、ビューは通常どおりコンテンツをレンダリングし、その結果が
下位レベルのビットマップでキャプチャされます。その後は、ビューのジオメトリに対する変更に
よって必ずしもビットマップが再作成されるとは限りません。代わりに、ビットマップを新しい境界
に合わせて拡大縮小するか、単にビューのいずれかの頂点または辺に固定するかが、contentModeプ
ロパティの値によって決定されます。
ビューのコンテンツモードは、以下の処理を実行するときに適用されます。
●
ビューのframeまたはboundsの矩形の幅や高さを変更する。
●
ビューのtransformプロパティに拡大縮小を伴う変換を割り当てる。
デフォルトでは、ほとんどのビューのcontentModeプロパティはUIViewContentModeScaleToFill
に設定されています。この場合、ビューのコンテンツは新しいフレームサイズに合わせて拡大縮小さ
れます。図 1-2に、利用可能ないくつかのコンテンツモードでの結果を示します。図からわかるよう
に、すべてのコンテンツモードでビューの境界一杯までコンテンツが表示されるわけではありませ
ん。また、境界一杯に表示すると、ビューのコンテンツにゆがみが発生する場合があります。
図 1-2
コンテンツモードの比較
コンテンツモードはビューのコンテンツを再利用する場合に適していますが、特に拡大縮小やサイズ
変更の操作中にカスタムビューで再描画したい場合には、コンテンツモードを
UIViewContentModeRedraw値に設定することもできます。ビューのコンテンツモードをこの値に設
定すると、システムはジオメトリの変更に応じてビューのdrawRect:メソッドを強制的に呼び出しま
す。一般的に、この値の使用は可能な限り避けてください。また、標準のシステムビューでは使用し
ないでください。
使用可能なコンテンツモードの詳細については、『UIView Class Reference 』を参照してください。
引き延ばし可能なビュー
ビューの一部を引き延ばし可能に指定すると、ビューのサイズが変更されたときに、引き延ばし可能
な部分のコンテンツだけが影響を受けるように設定できます。一般的に、引き延ばし可能な領域はボ
タンや、ビューの一部が一定のパターンの連続になっているようなビューに対して使用します。指定
した引き延ばし可能な領域は、ビューの一方または両方の軸に沿って引き延ばすことができます。
ビューを2軸に沿って引き延ばす場合は、ゆがみを生じないよう、ビューの端まで一定のパターンが
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
13
ビューとウインドウのアーキテクチャ
ビューのアーキテクチャの基本
連続している必要があります。図 1-3は、このゆがみがビューにどのように現れるかを示しています。
ビューの元のピクセルに応じた色が複製され、拡大されたビューの対応する領域が塗りつぶされま
す。
図 1-3
ボタンの背景の引き延ばし
ビューの引き延ばし可能領域は、contentStretchプロパティを使用して指定します。このプロパティ
には、値が0.0から1.0に正規化された矩形を設定できます。ビューを引き延ばすとき、システムは
これらの正規化された値にビューの現在の境界と倍率を乗算し、引き延ばしが必要な1つ以上のピク
セルを決定します。正規化された値を使用するため、ビューの境界を変更するごとにcontentStretch
プロパティを更新する必要はありません。
ビューのコンテンツモードも、ビューの引き延ばし可能な領域をどのように使用するかに影響しま
す。引き延ばし可能な領域は、コンテンツモードがビューのコンテンツを拡大縮小するときにだけ使
用されます。つまり、引き延ばし可能なビューはUIViewContentModeScaleToFill、
UIViewContentModeScaleAspectFit、およびUIViewContentModeScaleAspectFillコンテンツモー
ドのみでサポートされます。コンテンツを辺または頂点に固定する(したがって、実際にはコンテン
ツを拡大縮小しない)コンテンツモードを指定した場合、ビューは引き延ばし可能な領域を無視しま
す。
注意: ビューの背景を指定するときには、引き延ばし可能なUIImageオブジェクトを作成す
る代わりに、contentStretchプロパティを使用することをお勧めします。引き延ばし可能
なビューは完全にCore Animationレイヤで処理され、一般的にパフォーマンスが優れていま
す。
組み込みアニメーションのサポート
各ビューの下位レベルにレイヤオブジェクトがあることの利点の1つは、ビューに関するさまざまな
変更を簡単にアニメーション化できることです。アニメーションはユーザに情報を伝える有効な方法
であるため、アプリケーションの設計中は常にアニメーションの使用を考慮するようにしてくださ
い。UIViewクラスの多くのプロパティはアニメーション化可能です。つまり、ある値から別の値へ
のアニメーションが半自動でサポートされています。これらのアニメーション化可能なプロパティで
は、以下の操作だけでアニメーションを実行できます。
1.
UIKitにアニメーションを実行することを通知します。
2.
プロパティの値を変更します。
UIViewオブジェクトのアニメーション化可能なプロパティは、以下のとおりです。
frame - ビューの位置とサイズの変更をアニメーション化できます。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
14
ビューとウインドウのアーキテクチャ
ビューのアーキテクチャの基本
bounds - ビューのサイズの変更をアニメーション化できます。
center - ビューの位置をアニメーション化できます。
transform - ビューを回転または拡大縮小できます。
alpha - ビューの透明度を変更できます。
backgroundColor - ビューの背景色を変更できます。
contentStretch - ビューのコンテンツの引き延ばし方法を変更できます。
アニメーションが非常に重要となる場面として、ビューセット間にトランジションを設定する場合が
あります。一般的には、ユーザインターフェイスの大幅な変更に関するアニメーションを管理するに
は、ビューコントローラを使用します。たとえば、上位レベルから下位レベルの情報までナビゲー
ションを必要とするインターフェイスでは、一般的にナビゲーションコントローラを使用して次のレ
ベルのデータを表示し、ビュー間のトランジションを管理します。ただし、ビューコントローラの代
わりにアニメーションを使用して、ビューの2つのセット間のトランジションを作成することもでき
ます。標準のビューコントローラアニメーションでは希望する結果が得られない場合は、この方法を
使用できます。
UIKitのクラスを使用して作成するアニメーションのほかに、Core Animationレイヤを使用してアニメー
ションを作成することもできます。レイヤレベルで処理を行うことにより、アニメーションのタイミ
ングやプロパティをより詳細に制御できます。
ビューベースのアニメーションを実行する方法については、“アニメーション” (60 ページ)を参照
してください。Core Animationを使用してアニメーションを作成する方法については、『Core Animation
Programming Guide 』および『Core Animation Cookbook 』を参照してください。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
15
ビューとウインドウのアーキテクチャ
ビューのジオメトリと座標系
ビューのジオメトリと座標系
UIKitのデフォルトの座標系は左上隅を原点とし、原点から下向きおよび右向きに軸が定義されていま
す。座標値は浮動小数点数を使用して表され、基になる画面の解像度にかかわらず、コンテンツの正
確なレイアウトと配置が可能です。図 1-4に、この座標系と画面との関係を示します。画面の座標系
のほかに、ウインドウとビューでは独自のローカル座標系が定義され、座標を画面との相対で指定す
る代わりに、ビューまたはウインドウの原点を基準に指定することができます。
図 1-4
UIKitの座標系の向き
すべてのビューおよびウインドウで独自のローカル座標系が定義されるため、常に現在どの座標系が
有効であるかを意識する必要があります。ビューに描画する場合やビューのジオメトリを変更する場
合は、いずれかの座標系を基準にして実行します。描画の場合は、ビュー独自の座標系を基準に座標
を指定します。ジオメトリの変更の場合は、スーパービューの座標系を基準に座標を指定します。
UIWindowおよびUIViewクラスのどちらにも、座標系の変換に役立つメソッドが用意されています。
Important: 一部のiOSテクノロジーで定義されるデフォルト座標系は、原点と軸の向きがUIKitの座
標系と異なります。たとえば、Core GraphicsおよびOpenGL ESで使用される座標系では、ビューま
たはウインドウの左下隅が原点となり、y軸は画面に対して上向きになります。コンテンツを描画
または作成するときに、コードでこれらの違いを考慮し、必要に応じて座標値(または座標系の
デフォルトの向き)を調整する必要があります。
frame、bounds、およびcenterプロパティの関係
ビューオブジェクトは、frame、bounds、centerの各プロパティを使用して、ビューのサイズと位
置を追跡します。
●
frameプロパティにはフレーム矩形が含まれ、ビューのサイズと位置をスーパービューの座標系
で指定します。
●
boundsプロパティには境界矩形が含まれ、ビューのサイズ(およびコンテンツの原点)をビュー
のローカル座標系で指定します。
●
centerプロパティには、スーパービューの座標系に対する、ビューの既知の中心点が含まれま
す。
現在のビューのジオメトリを操作する場合は、主にcenterおよびframeプロパティを使用します。た
とえば、実行時にビュー階層を構築したりビューの位置またはサイズを変更する場合は、これらのプ
ロパティを使用します。ビューの位置だけを変更する(サイズは変更しない)場合、よく使われるの
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
16
ビューとウインドウのアーキテクチャ
ビューのジオメトリと座標系
はcenterプロパティを使用する方法です。ビューの変換に拡大縮小または回転の要素が追加されて
いる場合でも、centerプロパティの値は常に有効です。frameプロパティの値はこれと異なり、ビュー
の変換が恒等変換でない場合は、値が無効と見なされます。
描画中は、主にboundsプロパティを使用します。境界矩形は、ビュー独自のローカル座標系で表現
されます。この矩形のデフォルトの原点は (0, 0) で、サイズはフレーム矩形のサイズに一致します。
この矩形内に描画した内容はすべて、ビューに表示するコンテンツの一部となります。境界矩形の原
点を変更する場合は、新しい矩形内に描画した内容がビューに表示するコンテンツの一部となりま
す。
図 1-5は、画像ビューのフレーム矩形と境界矩形の関係を示しています。図では、画像ビューの左上
隅がスーパービューの座標系で (40, 40) の位置に配置され、矩形のサイズは240x380ポイントとなって
います。境界矩形については、原点は (0, 0) で、矩形のサイズは同様に240x380ポイントとなります。
図 1-5
ビューのフレームと境界の関係
frame、bounds、およびcenterプロパティはそれぞれ独立して変更できますが、各プロパティを変
更するとほかのプロパティに以下のように影響します。
●
frameプロパティを設定する場合、boundsプロパティのサイズ値が、フレーム矩形の新しいサイ
ズに一致するように変更されます。同様に、centerプロパティの値もフレーム矩形の新しい中心
点に一致するように変更されます。
●
centerプロパティを設定する場合、それに応じてframeの原点の値が変更されます。
●
boundsプロパティのサイズを設定する場合、frameプロパティのサイズ値が、境界矩形の新しい
サイズに一致するように変更されます。
デフォルトでは、ビューのフレームはスーパービューのフレームに合わせて切り取られません。した
がって、スーパービューのフレームの外側にあるサブビューはそのままレンダリングされます。この
動作は、スーパービューのclipsToBoundsプロパティをYESに設定することで変更できます。サブ
ビューが境界に合わせて視覚的に切り取られるかどうかにかかわらず、タッチイベントでは常にター
ゲットビューのスーパービューの境界矩形が考慮されます。つまり、スーパービューの境界矩形の外
側にあるビューで発生したタッチイベントは、そのビューに送信されません。
座標系の変換
座標系の変換により、ビュー(または、そのコンテンツ)をすばやく簡単に変更することができま
す。アフィン変換は、ある座標系の点を別の座標系にマッピングする方法を指定する、数学の行列で
す。アフィン変換をビュー全体に適用して、ビューのサイズ、位置、または向きをスーパービューに
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
17
ビューとウインドウのアーキテクチャ
ビューのジオメトリと座標系
対して相対的に変更できます。また、アフィン変換を描画コード内で使用して、レンダリングされる
コンテンツの部分ごとに同様の操作を実行することもできます。このため、アフィン変換を適用する
方法はコンテキストによって異なります。
●
●
ビュー全体を変更する場合は、ビューのtransformプロパティでアフィン変換を変更します。
ビューのdrawRect:メソッドでコンテンツの特定の部分だけを変更する場合は、アクティブなグ
ラフィックスコンテキストに関連付けられているアフィン変換を変更します。
アニメーションを実装するときには、ビューのtransformプロパティを変更するのが一般的です。た
とえば、このプロパティを使用して、ビューを中心点の周りに回転するアニメーションを作成できま
す。スーパービューの座標空間内でビューの位置やサイズを変更する場合など、ビューに永続的な変
更を行う場合は、このプロパティを使用しません。このような変更では、ビューのフレーム矩形を変
更してください。
注意: ビューのtransformプロパティを変更する場合、すべての変換はビューの中心点を基
準に実行されます。
ビューのdrawRect:メソッドでは、アフィン変換を使用して描画する項目の位置と向きを設定しま
す。ビュー内の特定の位置にオブジェクトを固定するよりも、各オブジェクトを (0, 0) などの固定点
を基準に作成しておき、描画の直前に変換を使用してオブジェクトの位置を設定する方が簡単です。
この場合、ビュー内でオブジェクトの位置が変更されたときに必要な操作は、変換を変更することだ
けです。この方法は、オブジェクトを新しい位置に作成し直すよりも高速で、負荷も小さくなりま
す。グラフィックスコンテキストに関連付けられたアフィン変換はCGContextGetCTM関数を使用して
取得でき、関連するCore Graphics関数を使用して描画中にこの変換を設定または変更できます。
現在の変換行列(CTM)は、ある時点で使用中のアフィン変換です。ビュー全体のジオメトリを操作
する場合、CTMはビューのtransformプロパティの保存されたアフィン変換です。drawRect:メソッ
ド内では、CTMはアクティブなグラフィックスコンテキストに関連付けられたアフィン変換です。
各サブビューの座標系は、親ビューの座標系の上に構築されています。したがって、ビューのtransform
プロパティを変更すると、変更はビューとそのすべてのサブビューに影響します。ただし、これらの
変更は、画面上でのビューの最終的なレンダリングにのみ影響します。各ビューはコンテンツを描画
し、自身の境界に対して相対的にサブビューをレイアウトするため、描画およびレイアウト中はスー
パービューの変換を無視できます。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
18
ビューとウインドウのアーキテクチャ
ビューのジオメトリと座標系
図 1-6は、レンダリング時に2つの回転が合成される様子を示しています。ビューのdrawRect:メソッ
ド内で、図形に45度の回転を適用すると、その図形は45度回転して表示されます。続いてビューに45
度の回転を適用すると、図形は90度回転して表示されます。図形は描画したビューを基準に45度回転
されているだけですが、ビューの回転により、さらに45度回転されて表示されます。
図 1-6
ビューとそのコンテンツの回転
Important: ビューのtransformプロパティが恒等変換でない場合、そのビューのframeプロパティ
の値は未定義となり、無視する必要があります。ビューに変換を適用する場合は、ビューのbounds
およびcenterプロパティを使用して、ビューのサイズと位置を取得する必要があります。サブ
ビューのフレーム矩形はビューの境界に対して相対的であるため、有効なままです。
ビューのtransformプロパティを実行時に変更する方法については、“ビューの平行移動、拡大縮小、
回転” (45 ページ)を参照してください。変換を使用して描画中にコンテンツを配置する方法につい
ては、『Drawing and Printing Guide for iOS 』を参照してください。
ポイントとピクセル
iOSでは、すべての座標値および距離を指定するときに、ポイントを単位とする浮動小数点値を使用
します。実際のポイントのサイズはデバイスごとに異なり、あまり重要ではありません。ポイントを
理解する上で重要な点は、ポイント指定によって描画の基準となる一定の尺度が提供されるというこ
とです。
表 1-1に、iOSベースのデバイスの縦長の向きでの画面サイズ(ポイント単位)を示します。値は、画
面のサイズを幅、高さの順に示しています。これらの画面サイズに合わせてインターフェイスを設計
する限り、ビューはそれぞれ対応するタイプのデバイスで正しく表示されます。
表 1-1
iOSベースのデバイスの画面サイズ
デバイス
画面サイズ(ポイント単位)
4インチのRetinaディスプレイを搭載したiPhoneおよびiPod touch
デバイス
320×568
その他のiPhoneおよびiPod touchデバイス
320×480
iPad
768x1024
それぞれのタイプのデバイスで使用されるポイントベースの計測方法で、ユーザ座標空間が定義され
ます。これは、ほぼすべてのコードで使用する標準の座標空間です。たとえば、ビューのジオメトリ
を操作するときや、Core Graphics関数を呼び出してビューのコンテンツを描画するときには、ポイン
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
19
ビューとウインドウのアーキテクチャ
実行時のビューの相互作用モデル
トとユーザ座標空間を使用します。ユーザ座標空間の座標はデバイスの画面上のピクセルに直接マッ
ピングされることもありますが、これが常に当てはまるとは想定しないでください。代わりに、常に
次のことに注意してください。
1ポイントは必ずしも画面上の1ピクセルに対応しない
デバイスレベルでは、ビューで指定した座標はすべて、ある時点でピクセルに変換される必要があり
ます。ただし、ユーザ座標空間のポイントをデバイス座標空間のピクセルにマッピングする処理は、
通常、システムによって行われます。UIKitとCore Graphicsはどちらも主にベクトルベースの描画モデ
ルを使用し、このモデルではすべての座標値がポイントで指定されます。したがって、Core Graphics
を使用して曲線を描画する場合、基になる画面の解像度にかかわらず、同じ値を使用して曲線を指定
します。
イメージの操作や、OpenGL ESなどのその他のピクセルベースのテクノロジーの使用が必要な場合は、
iOSがピクセルの管理をサポートします。アプリケーションバンドルにリソースとして格納された静
的なイメージファイルについては、イメージを別のピクセル密度で指定するための規則や、現在の画
面解像度に最適なイメージをロードするための規則が、iOSで定義されています。ピクセルベースの
描画コードを手動で調整して、より解像度の高い画面に対応できるように、ビューは現在の倍率に関
する情報も提供します。ピクセルベースのコンテンツを別の画面解像度で処理する手法は、『Drawing
and Printing Guide for iOS 』の「Supporting High-Resolution Screens In Views」で説明されています。
実行時のビューの相互作用モデル
ユーザがユーザインターフェイスを操作したり、自分のコードでプログラムの中で何らかの変更を加
えたりしたときは、それらの操作を処理するために、UIKitの内部で複雑なイベントシーケンスが発生
します。シーケンス中の特定のポイントで、UIKitはアプリケーションに代わってビュークラスを呼び
出し、応答する機会を与えます。これらの呼び出しポイントを理解することは、ビューがどこでシス
テムに組み込まれるかを理解する上で重要です。図 1-7は、ユーザが画面にタッチすることで始まり、
グラフィックスシステムがそれに応答して画面のコンテンツを更新することで終わる、基本的なイベ
ントのシーケンスを示しています。プログラムによって開始されたアクションでも、同じイベントの
シーケンスが発生します。
図 1-7
UIKitとビューオブジェクトとの対話
以下の手順では、図 1-7 (20 ページ)のイベントシーケンスをさらに細かく分け、各ステージで何
が発生し、それに対してアプリケーションがどのように応答するかを説明しています。
1.
ユーザが画面にタッチします。
2.
ハードウェアがUIKitフレームワークにタッチイベントを報告します。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
20
ビューとウインドウのアーキテクチャ
実行時のビューの相互作用モデル
3.
UIKitフレームワークは、タッチをUIEventオブジェクトにパッケージ化し、これを適切なビュー
にディスパッチします(UIKitがイベントをビューに送付する方法の詳細については、『Event
Handling Guide for iOS 』を参照してください)。
4.
ビューのイベント処理コードが、イベントに応答します。たとえば、コードは以下を実行しま
す。
●
ビューまたはサブビューのプロパティ(frame、bounds、alphaなど)を変更します。
●
setNeedsLayoutメソッドを呼び出して、ビュー(または、そのサブビュー)にレイアウト
の更新が必要であることを示すマークを付けます。
●
setNeedsDisplayまたはsetNeedsDisplayInRect:メソッドを呼び出して、ビュー(また
は、そのサブビュー)に再描画が必要であることを示すマークを付けます。
●
データの一部が変更されたことをコントローラに通知する。
もちろん、ビューが実行することや呼び出すメソッドを決定するのはデベロッパです。
5.
何らかの理由でビューのジオメトリが変更された場合は、UIKitが以下の規則に従ってサブビュー
を更新します。
a.
ビューに自動サイズ変更の規則を設定している場合は、UIKitがその規則に従って各ビューを
調整します。自動サイズ変更規則の動作については、“自動サイズ変更規則を使用した自動的
なレイアウト変更の処理” (48 ページ)を参照してください。
b.
ビューがlayoutSubviewsメソッドを実装している場合は、UIKitがこれを呼び出します。
カスタムビューでこのメソッドをオーバーライドし、これを使用してサブビューの位置とサ
イズを調整できます。たとえば、大きなスクロール可能領域を持つビューでは、メモリに収
まらないような大きなビューを1つ作成するのではなく、複数のサブビューを「タイル」とし
て使用する必要があります。このメソッドの実装で、ビューは現在画面外にあるサブビュー
を非表示にするか、これらを再配置して新しく表示されるコンテンツの描画に使用します。
このプロセスの一部として、ビューのレイアウトコードは再描画を必要とするビューを無効
にすることもできます。
6.
ビューのいずれかの部分に再描画が必要であることを示すマークが付けられた場合、UIKitはビュー
に再描画を要求します。
drawRect:メソッドを明示的に定義しているカスタムビューでは、UIKitがそのメソッドを呼び出
します。このメソッドの実装では、ビューの指定された領域をできるだけ早く再描画し、ほかに
は何も処理しないようにします。ここでは、その他のレイアウト変更やアプリケーションのデー
タモデルの変更は行わないでください。このメソッドの目的は、ビューの視覚的なコンテンツを
更新することです。
標準のシステムビューは、一般的にdrawRect:メソッドを実装しませんが、この時点で描画を管
理しています。
7.
更新されたビューは、アプリケーションで表示中の残りのコンテンツと合成され、表示のために
グラフィックスハードウェアに送信されます。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
21
ビューとウインドウのアーキテクチャ
実行時のビューの相互作用モデル
8.
グラフィックスハードウェアは、レンダリングされたコンテンツを画面に転送します。
注意: 上の更新モデルは、主に標準のシステムビューと描画手法を使用するアプリケーショ
ンに適用されます。描画にOpenGL ESを使用するアプリケーションは、一般的に1つのフル
スクリーンビュを設定して、関連するOpenGL ESグラフィックスコンテキストに直接描画し
ます。この場合、ビューはタッチイベントを処理しますが、ビューがフルスクリーンである
ため、サブビューの配置は必要ありません。OpenGL ESの使用方法については、『OpenGL ES
Programming Guide for iOS 』を参照してください。
前述の一連のステップにおける、カスタムビューのための主な統合点は以下のとおりです。
●
イベント処理メソッド:
●
touchesBegan:withEvent:
●
touchesMoved:withEvent:
●
touchesEnded:withEvent:
●
touchesCancelled:withEvent:
●
layoutSubviewsメソッド
●
drawRect:メソッド
オーバーライドするビューのメソッドとしては、これらのメソッドが最も一般的ですが、すべてを
オーバーライドする必要はありません。ジェスチャリコグナイザを使用してイベントを処理する場合
は、いずれのイベント処理メソッドもオーバーライドする必要がありません。同様に、ビューにサブ
ビューが含まれていない場合や、ビューのサイズが変更されない場合は、layoutSubviewsメソッド
をオーバーライドする必要がありません。さらに、ビューのコンテンツが実行時に変更可能で、描画
にUIKitやCore Graphicsなどのネイティブなテクノロジーを使用している場合、オーバーライドが必要
なのはdrawRect:メソッドのみです。
これらは主な統合場所であり、統合できる場所はこれだけではないことにも注意してください。UIView
クラスのいくつかのメソッドは、サブクラスのオーバーライドポイントとなるように設計されていま
す。『UIView Class Reference 』のメソッドの説明で、どのメソッドがカスタム実装でのオーバーライ
ドに適しているかを確認してください。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
22
ビューとウインドウのアーキテクチャ
ビューを効果的に使用するためのヒント
ビューを効果的に使用するためのヒント
カスタムビューは、標準のシステムビューで提供されていないものを描画する必要があるときに有用
ですが、ビューの良好なパフォーマンスを保証する必要があります。UIKitは実行できる処理をすべて
行って、ビューに関連する動作を最適化し、カスタムビューで良好なパフォーマンスを達成するため
の支援を行います。以下のヒントについて考慮すると、UIKitがこれらの処理を行う際に役立ちます。
Important: 描画コードを最適化する前に、常にビューの現在のパフォーマンスに関するデータを
収集してください。現在のパフォーマンスを測定することで、実際に問題があるかどうかを確認
できます。また、問題がある場合は、最適化した結果を比較する際の基準として使用できます。
ビューには必ずしも対応するビューコントローラがあるとは限らない
アプリケーションで、個々のビューとビューコントローラの間に1対1の関係があることはまれです。
ビューコントローラの役割はビュー階層を管理することで、一般的にビュー階層は自己完結型の機能
を実装するために使用される複数のビューで構成されます。iPhoneアプリケーションの場合、一般的
には各ビュー階層が画面全体に表示されますが、iPadアプリケーションでは、1つのビュー階層は画
面の一部分しか占有しません。
アプリケーションのユーザインターフェイスを設計するときに、ビューコントローラの役割を考慮す
ることは重要です。ビューコントローラは、画面上でのビューの表示の制御、画面からのビューの削
除の制御、メモリ不足の警告に対するメモリの解放、インターフェイスの向きの変更に応じたビュー
の回転など、多くの重要な処理を提供します。これらの処理を使用しなければ、アプリケーションは
正しく動作しないか、予期しない動作を行います。
ビューコントローラの詳細とアプリケーションにおけるその役割については、『View Controller
Programming Guide for iOS 』を参照してください。
カスタム描画を最小限にする
カスタム描画が必要な場合もありますが、可能な場合は使用を避けるようにしてください。カスタム
描画が本当に必要となるのは、目的の外観や機能が既存のシステムビュークラスで提供されていない
ときだけです。既存のビューを組み合わせてコンテンツを構成できる場合は、これらのビューオブ
ジェクトを組み合わせてカスタムビュー階層を構築することをお勧めします。
コンテンツモードを利用する
コンテンツモードは、ビューの再描画にかかる時間を最小化します。デフォルトでは、ビューは
UIViewContentModeScaleToFillコンテンツモードを使用し、ビューのフレーム矩形に合わせて
ビューの既存のコンテンツを拡大縮小します。必要な場合は、このモードを変更してコンテンツを調
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
23
ビューとウインドウのアーキテクチャ
ビューを効果的に使用するためのヒント
整できますが、可能であればUIViewContentModeRedrawコンテンツモードの使用は避けてください。
現在のコンテンツモードにかかわらず、setNeedsDisplayまたはsetNeedsDisplayInRect:を呼び出
すことで、常にビューのコンテンツを強制的に再描画できます。
可能な場合は常にビューを不透明として宣言する
UIKitでは、各ビューのopaqueプロパティを使用して、合成処理を最適化するよう設定できます。カ
スタムビューでこのプロパティの値をYESに設定すると、UIKitにビューの背面にあるコンテンツをレ
ンダリングする必要がないことが通知されます。レンダリング少なければ、描画コードのパフォーマ
ンスを向上させることができ、一般的にはこの設定が推奨されます。もちろん、opaqueプロパティ
をYESに設定した場合、ビューは境界矩形一杯に完全に不透明なコンテンツを表示する必要がありま
す。
スクロール時のビューの描画動作を調整する
スクロールでは、短時間に大量のビューの更新が発生する場合があります。ビューの描画コードが適
切に調整されていない場合、ビューのスクロール時のパフォーマンスが低下する可能性があります。
ビューのコンテンツを常に最新に維持しようとするよりも、スクロール操作を開始するときに、ビュー
の動作を変更することを検討してください。たとえば、レンダリングされたコンテンツの品質を一時
的に下げたり、スクロールの実行中にコンテンツモードを変更するなどの方法が考えられます。スク
ロールを停止したら、ビューを元の状態に戻し、必要に応じてコンテンツを更新します。
サブビューの埋め込みでコントロールをカスタマイズしない
標準のシステムコントロール(UIControlから継承するオブジェクト)にサブビューを追加すること
は技術的に可能ですが、この方法でコントロールをカスタマイズしないでください。コントロールを
カスタマイズする場合は、コントロールクラス自身の明示的で十分に検証されたインターフェイスを
通して行います。たとえば、UIButtonクラスにはボタンのタイトルや背景イメージを設定するメソッ
ドが含まれています。定義済みのカスタマイズ方法を使用することで、コードは常に正しく動作しま
す。これらのメソッドを使用せずに、ボタン内にカスタム画像ビューやラベルを埋め込んだ場合、ア
プリケーションはその時点で、または後にボタンの実装が変更された時点で正しく動作しなくなる可
能性があります。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
24
ウインドウ
すべてのiOSアプリケーションには少なくとも1つのウインドウ(UIWindowクラスのインスタンス)
が必要で、アプリケーションによっては複数のウインドウが含まれる場合もあります。ウインドウオ
ブジェクトには、いくつかの役割があります。
●
●
●
アプリケーションが表示しているコンテンツを含みます。
タッチイベントをビューやその他のアプリケーションオブジェクトに送信する際に、重要な役割
を果たします。
アプリケーションのビューコントローラと連携して、向きの変更を容易にします。
iOSでは、ウインドウはタイトルバー、閉じるボックス、またはその他の視覚的な装飾を持ちません。
ウインドウは常に、1つまたは複数のビューのための空のコンテナです。また、アプリケーションは
新しいウインドウを表示することでコンテンツを変更しません。表示されているコンテンツを変更す
る場合は、ウインドウの最前面にあるビューを変更します。
ほとんどのiOSアプリケーションは、ウインドウを1つだけ作成し、終了するまでそのウインドウを使
用します。このウインドウはデバイスのメイン画面全体に表示され、アプリケーション起動後の初期
の段階で、アプリケーションのメインnibファイルからロードされます(または、プログラムにより
作成されます)。ただし、アプリケーションがビデオ出力用に外部ディスプレイの使用をサポートす
る場合は、追加ウインドウを作成してコンテンツを外部ディスプレイに表示できます。一般的に、そ
の他のウインドウはすべてシステムによって作成され、通常は特定のイベント(電話の着信など)に
応答して作成されます。
ウインドウの使用を伴うタスク
多くのアプリケーションでは、アプリケーションがウインドウとやり取りするのは、起動時にウイン
ドウを作成するときだけです。ただし、アプリケーションのウインドウオブジェクトを使用して、ア
プリケーションに関するいくつかのタスクを実行できます。
●
ウインドウを使用して、点および矩形をウインドウのローカル座標系に変換したり、その逆を行
います。たとえば、ウインドウの座標で値が与えられている場合は、その値を使用する前に特定
のビューの座標系に変換できます。座標を変換する方法については、“ビュー階層での座標の変
換” (46 ページ)を参照してください。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
25
ウインドウ
ウインドウの作成と設定
●
ウインドウの通知を使用して、ウインドウに関連する変更を追跡します。ウインドウは表示と非
表示が切り替わったときや、キーウインドウになったとき、またはキーウインドウでなくなった
ときに通知を生成します。これらの通知を使用して、アプリケーションの別の部分で操作を実行
できます。詳細については、「“ウインドウの変更の監視” (29 ページ)を参照してください。
ウインドウの作成と設定
アプリケーションのメインウインドウは、プログラムで作成および設定するか、Interface Builderを使
用して作成および設定できます。いずれの場合も、起動時にウインドウを作成し、作成したウインド
ウを保持して、ウインドウへの参照をアプリケーションのデリゲートオブジェクトに格納する必要が
あります。アプリケーションが追加のウインドウを作成する場合は、そのウインドウが必要になるま
で作成を遅らせます。たとえば、アプリケーションが外部ディスプレイへのコンテンツの表示をサ
ポートする場合は、ディスプレイが接続されるのを待ってから、対応するウインドウを作成します。
アプリケーションがフォアグラウンドまたはバックグラウンドのどちらで起動されるかにかかわら
ず、アプリケーションのメインウインドウは常に起動時に作成する必要があります。ウインドウの作
成と設定自体は、負荷の大きい操作ではありません。ただし、アプリケーションがそのままバックグ
ラウンドで起動される場合は、アプリケーションがフォアグラウンドになるまでウインドウの表示を
避ける必要があります。
Interface Builderでのウインドウの作成
Interface Builderを使用したアプリケーションのメインウインドウの作成は、Xcodeプロジェクトのテ
ンプレートが必要な処理を行うため簡単です。すべての新しいXcodeアプリケーションプロジェクト
には、アプリケーションのメインウインドウを含むメインnibファイルが(通常は、MainWindow.xib
のような名前で)含まれます。また、これらのテンプレートは、アプリケーションデリゲートオブ
ジェクトにウインドウのアウトレットも定義します。コードでウインドウオブジェクトにアクセスす
るには、このアウトレットを使用します。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
26
ウインドウ
ウインドウの作成と設定
Important: Interface Builderでウインドウを作成する場合は、「Attributes」インスペクタの「Launch」
オプションで「Full Screen」を有効にすることをお勧めします。このオプションが有効でない場
合、ウインドウがターゲットデバイスの画面より小さいと、一部のビューでタッチイベントが受
信されません。これは、ウインドウが(すべてのビューと同様に)境界矩形の外側にあるタッチ
イベントを受信しないためです。ビューはデフォルトでウインドウの境界に合わせて切り取られ
ることがないため、ビューは表示されますが、イベントはビューに到達しません。「Launch」オ
プションで「Full Screen」を有効にすると、ウインドウのサイズが現在の画面に合わせて適切に設
定されます。
Interface Builderを使用するようにプロジェクトを更新している場合、Interface Builderを使用したウイ
ンドウの作成は、単にウインドウオブジェクトをnibファイルにドラッグするだけです。もちろん、
以下の操作も必要です。
●
●
実行時にウインドウにアクセスするには、ウインドウをアウトレットに接続します。一般的に、
アウトレットはアプリケーションのデリゲートまたはnibファイルのFile's Ownerで定義されていま
す。
プロジェクトの更新計画で新しいnibファイルをアプリケーションのメインnibファイルにするこ
とが予定されている場合は、アプリケーションのInfo.plistファイルで、NSMainNibFileキー
をnibファイルの名前に設定する必要もあります。このキーの値を変更すると、アプリケーション
デリゲートのapplication:didFinishLaunchingWithOptions:メソッドが呼び出されるまで
に、nibファイルがロードされ利用可能になることが保証されます。
nibファイルを作成および設定する方法については、『Interface Builder User Guide 』を参照してくださ
い。実行時にnibファイルをアプリケーションにロードする方法については、『Resource Programming
Guide 』の「Nib Files」を参照してください。
プログラムによるウインドウの作成
アプリケーションのメインウインドウをプログラムで作成する場合は、アプリケーションデリゲート
のapplication:didFinishLaunchingWithOptions:メソッドに、次のようなコードを追加する必要
があります。
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]
autorelease];
上の例では、self.windowはウインドウオブジェクトを保持するように設定されたアプリケーション
デリゲートの宣言済みプロパティと見なされます。外部ディスプレイ用のウインドウを作成している
場合は、これを別の変数に割り当て、そのディスプレイを表すメイン以外のUIScreenオブジェクト
の境界を指定する必要があります。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
27
ウインドウ
ウインドウの作成と設定
ウインドウを作成するときには、常にウインドウのサイズを画面の境界一杯に設定してください。ス
テータスバーやその他の項目を考慮して、ウインドウのサイズを小さくする必要はありません。ス
テータスバーは常にウインドウの最前面に表示されるため、ステータスバーを考慮して小さくする必
要があるのは、ウインドウに配置するビューだけです。また、ビューコントローラを使用している場
合は、ビューコントローラがビューのサイズを自動的に変更します。
ウインドウへのコンテンツの追加
一般的に、各ウインドウは(対応するビューコントローラで管理される)ルートビューオブジェクト
を1つ持ち、このオブジェクトにコンテンツを表すほかのビューがすべて含まれています。1つのルー
トビューを使用することでインターフェイスを変更するプロセスは簡略化され、新しいコンテンツを
表示するために必要な操作はルートビューを置き換えることだけになります。ウインドウにビューを
追加するには、addSubview:メソッドを使用します。たとえば、ビューコントローラによって管理さ
れるビューを追加するには、以下のようなコードを使用します。
[window addSubview:viewController.view];
上のコードの代わりに、nibファイルでウインドウのrootViewControllerプロパティを設定すること
もできます。このプロパティを使用すると、プログラムの代わりにnibファイルを使用してウインド
ウのルートビューを設定できます。ウインドウがnibファイルからロードされるときにこのプロパティ
が設定されていると、UIKitは関連付けられたビューコントローラから自動的にビューをウインドウの
ルートビューとして追加します。このプロパティはルートビューを追加するためにだけ使用され、
ビューコントローラと通信するためにウインドウが使用することはありません。
ウインドウのルートビューには、いずれのビューでも使用できます。インターフェイスの設計に応じ
て、ルートビューは1つ以上のサブビューのコントローラとして動作する汎用のUIViewオブジェク
ト、標準のシステムビュー、または各自で定義したカスタムビューのいずれかになります。一般的に
ルートビューとして使用される標準のシステムビューには、スクロールビュー、テーブルビュー、画
像ビューなどがあります。
ウインドウのルートビューを設定するとき、ウインドウ内でビューの初期サイズと位置を設定する必
要があります。ステータスバーを含まないアプリケーション、または半透明のステータスバーを表示
するアプリケーションでは、ビューのサイズをウインドウのサイズに一致するように設定します。不
透明なステータスバーを表示するアプリケーションでは、ビューをステータスバーの下に配置し、サ
イズを適切に縮小します。ステータスバーの高さ分だけ小さくすることで、ビューの上部がステータ
スバーに隠されるのを防ぎます。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
28
ウインドウ
ウインドウの変更の監視
注意: ウインドウのルートビューがコンテナビューコントローラ(タブバーコントローラ、
ナビゲーションコントローラ、分割ビューコントローラなど)によって提供される場合は、
ビューの初期サイズを各自で設定する必要はありません。ステータスバーの表示設定に基づ
いて、コンテナビューコントローラが自動的にビューのサイズを設定します。
ウインドウレベルの変更
各UIWindowオブジェクトには、設定可能なwindowLevelプロパティがあります。このプロパティは、
そのウインドウをほかのウインドウに対してどのように配置するかを決定します。ほとんどの場合、
アプリケーションのウインドウのレベルは変更する必要がありません。新しいウインドウは、作成時
に通常のウインドウレベルに自動的に関連付けられます通常のウインドウレベルは、ウインドウがア
プリケーション関連のコンテンツを表示することを示します。これより上位のウインドウレベルは、
アプリケーションコンテンツの前面に表示する必要がある情報(システムステータスバーや警告メッ
セージ)用に予約されています。ウインドウをこれらのレベルに割り当てることもできますが、通常
この処理は特定のインターフェイスを使用するときにシステムによって行われます。たとえば、ス
テータスバーの表示と非表示を切り替えたり、警告ビューを表示するときに、システムは自動的に必
要なウインドウを作成し、これらの項目を表示します。
ウインドウの変更の監視
ウインドウの表示と非表示の切り替えをアプリケーション内で追跡する場合は、これらのウインドウ
に関する通知を使用します。
●
UIWindowDidBecomeVisibleNotification
●
UIWindowDidBecomeHiddenNotification
●
UIWindowDidBecomeKeyNotification
●
UIWindowDidResignKeyNotification
これらの通知は、アプリケーションのウインドウでのプログラムによる変更に応じて送信されます。
したがって、アプリケーションがウインドウの表示と非表示を切り替えるときには、
UIWindowDidBecomeVisibleNotificationおよびUIWindowDidBecomeHiddenNotificationの通知
が動作に応じて送信されます。アプリケーションがバックグラウンドの実行状態に移るとき、これら
の通知は送信されません。アプリケーションがバックグラウンドで実行され、ウインドウが画面に表
示されていない場合でも、アプリケーションのコンテキストではまだ表示されていると見なされま
す。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
29
ウインドウ
外部ディスプレイでのコンテンツの表示
UIWindowDidBecomeKeyNotificationおよびUIWindowDidResignKeyNotificationの通知は、どの
ウインドウがキーウインドウであるかを追跡する、つまり現在キーボードのイベントやその他のタッ
チ関連以外のイベントを受信しているウインドウを追跡するのに役立ちます。タッチイベントはタッ
チが発生したウインドウに送信されますが、座標値に関連付けられていないイベントはアプリケー
ションのキーウインドウに送信されます。キーウインドウになれるのは、常に1つのウインドウだけ
です。
外部ディスプレイでのコンテンツの表示
コンテンツを外部ディスプレイで表示する場合は、アプリケーションの追加ウインドウを作成し、こ
れを外部ディスプレイを表す画面オブジェクトに関連付ける必要があります。通常、新しいウインド
ウはデフォルトでメイン画面に関連付けられます。ウインドウの関連付けられた画面オブジェクトを
変更すると、そのウインドウのコンテンツは対応するディスプレイに送られます。ウインドウを正し
い画面に関連付けた後は、アプリケーションのメイン画面の場合と同様に、ウインドウにビューを追
加して表示することができます。
UIScreenクラスは、利用可能なハードウェアディスプレイを表す画面オブジェクトのリストを管理
します。通常、iOSベースのデバイスはメインディスプレイを表す画面オブジェクトを1つだけ持ちま
すが、外部ディスプレイへの接続をサポートするデバイスは、利用可能な追加の画面オブジェクトを
持つ場合があります。外部ディスプレイをサポートするデバイスには、Retinaディスプレイを備えた
iPhoneおよびiPod touchデバイスやiPadがあります。iPhone 3GSなどの古いデバイスは、外部ディスプ
レイをサポートしません。
注意: 外部ディスプレイは本質的にビデオ出力の接続であるため、外部ディスプレイに関連
付けられるウインドウでは、ビューおよびコントロールのタッチイベントを期待すべきでは
ありません。また、ウインドウのコンテンツを必要に応じて更新しなければなりません。し
たがって、メインウインドウのコンテンツをミラーリングする場合は、外部ディスプレイの
ウインドウ用に複製されたビューセットを作成し、これをメインウインドウのビューと一緒
に更新する必要があります。
外部ディスプレイにコンテンツを表示するプロセスは後のセクションで説明することにして、以下の
手順で基本プロセスを要約します。
1.
アプリケーションの起動時に、画面の接続と接続解除の通知を登録します。
2.
外部ディスプレイにコンテンツを表示するときに、ウインドウを作成して設定します。
●
UIScreenのscreensプロパティを使用して、外部ディスプレイの画面オブジェクトを取得し
ます。
●
UIWindowオブジェクトを作成して画面(またはコンテンツ)に合ったサイズに変更します。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
30
ウインドウ
外部ディスプレイでのコンテンツの表示
●
外部ディスプレイのUIScreenオブジェクトを、ウインドウのscreenプロパティに割り当て
ます。
●
コンテンツをサポートするために必要な場合は、画面オブジェクトの解像度を調整します。
●
ウインドウに適切なビューを追加します。
ウインドウを表示し、通常どおり更新します。
3.
画面の接続および接続解除に関する通知の処理
画面の接続と接続解除に関する通知は、外部ディスプレイへの変更を適切に処理するために重要で
す。ユーザがディスプレイを接続または接続解除すると、システムは適切な通知をアプリケーション
に送信します。これらの通知を使用してアプリケーションの状態を更新し、外部ディスプレイに関連
付けられたウインドウを作成または解放します。
接続と接続解除の通知に関して重要な点は、アプリケーションがバックグラウンドで一時停止されて
いるときでも、これらの通知が常に送信されてくることです。したがって、アプリケーションの実行
時に存在する予定のオブジェクト(たとえば、アプリケーションデリゲート)からの通知を監視する
のが最善の方法です。アプリケーションが一時停止している場合は、アプリケーションの停止状態が
終了し、フォアグラウンドまたはバックグラウンドで実行が開始されるまで、通知はキューに入れら
れます。
リスト 2-1に、接続および接続解除の通知を登録するためのコードを示します。このメソッドは、初
期化時にアプリケーションデリゲートによって呼び出されますが、アプリケーションの別の場所から
でもこれらの通知を登録できます。ハンドラメソッドの実装は、リスト 2-2 (32 ページ)に示して
います。
リスト 2-1
画面の接続および接続解除に関する通知の登録
- (void)setupScreenConnectionNotificationHandlers
{
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(handleScreenConnectNotification:)
name:UIScreenDidConnectNotification object:nil];
[center addObserver:self selector:@selector(handleScreenDisconnectNotification:)
name:UIScreenDidDisconnectNotification object:nil];
}
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
31
ウインドウ
外部ディスプレイでのコンテンツの表示
外部ディスプレイがデバイスに接続されたときにアプリケーションがアクティブな場合は、そのディ
スプレイ用に2つ目のウインドウを作成し、何らかのコンテンツを表示する必要があります。この場
合のコンテンツは、表示したい最終的なコンテンツである必要はありません。たとえば、アプリケー
ションで追加画面を使用するための準備が完了していない場合は、2つ目のウインドウを使用してプ
レースホルダコンテンツを表示できます。画面用のウインドウを作成しない場合、またはウインドウ
を作成してもそれを表示しない場合、外部ディスプレイには黒色の画面が表示されます。
リスト 2-2に、2つ目のウインドウを作成してコンテンツを表示する方法を示します。この例では、ハ
ンドラメソッドで、画面の接続通知を受け取るために使用するウインドウを作成します(接続と接続
解除の通知の登録については、リスト 2-1 (31 ページ)を参照)。接続通知のハンドラメソッドが2
つ目のウインドウを作成し、これを新しく接続された画面に関連付けます。続いて、アプリケーショ
ンのメインビューコントローラのメソッドを呼び出し、ウインドウにコンテンツを追加して表示しま
す。接続解除の通知のハンドラメソッドはウインドウを解放し、それに合わせて表示を調整できるよ
うにメインビューコントローラに通知します。
リスト 2-2
接続および接続解除に関する通知の処理
- (void)handleScreenConnectNotification:(NSNotification*)aNotification
{
UIScreen*
CGRect
newScreen = [aNotification object];
screenBounds = newScreen.bounds;
if (!_secondWindow)
{
_secondWindow = [[UIWindow alloc] initWithFrame:screenBounds];
_secondWindow.screen = newScreen;
// Set the initial UI for the window.
[viewController displaySelectionInSecondaryWindow:_secondWindow];
}
}
- (void)handleScreenDisconnectNotification:(NSNotification*)aNotification
{
if (_secondWindow)
{
// Hide and then delete the window.
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
32
ウインドウ
外部ディスプレイでのコンテンツの表示
_secondWindow.hidden = YES;
[_secondWindow release];
_secondWindow = nil;
// Update the main screen based on what is showing here.
[viewController displaySelectionOnMainScreen];
}
}
外部ディスプレイ用のウインドウの設定
ウインドウを外部画面に表示するには、ウインドウを正しい画面オブジェクトに関連付ける必要があ
ります。このプロセスでは、適切なUIScreenオブジェクトを決定し、このオブジェクトをウインド
ウのscreenプロパティに割り当てます。画面オブジェクトのリストは、screensのUIScreenクラス
メソッドから取得できます。このメソッドから返される配列には常に、メイン画面を表すオブジェク
トが少なくとも1つ含まれます。ほかのオブジェクトがある場合、そのオブジェクトは接続された外
部ディスプレイを表します。
リスト 2-3に、外部ディスプレイが接続されているかどうかを確認するために、アプリケーションの
起動時に呼び出されるメソッドを示します。外部ディスプレイが接続されている場合、メソッドはウ
インドウを作成して外部ディスプレイに関連付け、ウインドウを表示する前にプレースホルダコンテ
ンツを追加します。この例では、プレースホルダコンテンツは白色の背景と、表示するコンテンツが
ないことを示すラベルで構成されています。ウインドウを表示するために、このメソッドはhidden
を呼び出す代わりに、makeKeyAndVisibleプロパティを変更しています。これは、ウインドウに含
まれているのが静的なコンテンツだけで、ウインドウがイベントの処理に使用されないためです。
リスト 2-3
外部ディスプレイ用のウインドウの設定
- (void)checkForExistingScreenAndInitializeIfPresent
{
if ([[UIScreen screens] count] > 1)
{
// Associate the window with the second screen.
// The main screen is always at index 0.
UIScreen*
CGRect
secondScreen = [[UIScreen screens] objectAtIndex:1];
screenBounds = secondScreen.bounds;
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
33
ウインドウ
外部ディスプレイでのコンテンツの表示
_secondWindow = [[UIWindow alloc] initWithFrame:screenBounds];
_secondWindow.screen = secondScreen;
// Add a white background to the window
UIView*
whiteField = [[UIView alloc] initWithFrame:screenBounds];
whiteField.backgroundColor = [UIColor whiteColor];
[_secondWindow addSubview:whiteField];
[whiteField release];
// Center a label in the view.
NSString*
noContentString = [NSString stringWithFormat:@"<no content>"];
CGSize
stringSize = [noContentString sizeWithFont:[UIFont
systemFontOfSize:18]];
CGRect
labelSize = CGRectMake((screenBounds.size.width stringSize.width) / 2.0,
(screenBounds.size.height - stringSize.height)
/ 2.0,
stringSize.width, stringSize.height);
UILabel*
noContentLabel = [[UILabel alloc] initWithFrame:labelSize];
noContentLabel.text = noContentString;
noContentLabel.font = [UIFont systemFontOfSize:18];
[whiteField addSubview:noContentLabel];
// Go ahead and show the window.
_secondWindow.hidden = NO;
}
}
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
34
ウインドウ
外部ディスプレイでのコンテンツの表示
Important: ウインドウを表示する前に、常に画面をウインドウに関連付ける必要があります。現
在表示しているウインドウの画面を変更することもできますが、この操作は負荷が大きいため避
けてください。
外部画面のウインドウが表示されたらすぐに、ほかのウインドウと同様に更新を開始できます。必要
に応じてサブビューの追加と削除、サブビューのコンテンツの変更、ビューに対する変更のアニメー
ション化、およびコンテンツの無効化を実行できます。
外部ディスプレイの画面モードの設定
コンテンツに応じて、ウインドウを画面に関連付ける前に画面モードを変更できます。多くの画面は
複数の解像度をサポートし、一部の解像度ではピクセルのアスペクト比が異なる場合があります。画
面オブジェクトはデフォルトで最も一般的な画面モードを使用しますが、コンテンツに適した画面
モードに変更することができます。たとえば、OpenGL ESを使用するゲームを実装しているときに、
テクスチャが640x480ピクセルの画面に合わせて設計されている場合、デフォルト解像度がより高い
画面では画面モードを変更できます。
デフォルト以外の画面モードの使用を計画している場合は、画面をウインドウに割り当てる前に、使
用するモードをUIScreenオブジェクトに適用する必要があります。UIScreenModeクラスは、単一の
画面モードの属性を定義します。画面でサポートされるモードのリストは、availableModesプロパ
ティから取得でき、リストから要求を満たすモードを選択できます。
画面モードの詳細については、『UIScreenMode Class Reference 』を参照してください。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
35
ビュー
ビューオブジェクトはアプリケーションがユーザとやり取りを行う主な手段であるため、さまざまな
役割を担います。たとえば、以下のような処理を行います。
●
レイアウトとサブビューの管理
●
ビューは、デフォルトのサイズ変更動作を親ビューとの関連において独自に定義します。
●
ビューはサブビューのリストを管理できます。
●
ビューは必要に応じてサブビューのサイズと位置をオーバーライドできます。
●
●
●
ビューは自身の座標系で表した点を、ほかのビューまたはウインドウの座標系に変換できま
す。
描画とアニメーション
●
ビューはコンテンツを矩形領域に描画します。
●
ビューのプロパティには、新しい値への変化をアニメーション化できるものもあります。
イベント処理
●
ビューはタッチイベントを受信できます。
●
ビューはレスポンダチェーンに参加します。
この章では、ビューの作成、管理、および描画に関する手順と、ビュー階層のレイアウト操作および
管理操作に関する手順について説明します。ビューでタッチイベント(およびその他のイベント)を
処理する方法については、『Event Handling Guide for iOS 』を参照してください。
ビューオブジェクトの作成と設定
ビューはプログラムまたはInterface Builderで自己完結型のオブジェクトとして作成し、これらをビュー
階層にまとめて使用します。
Interface Builderを使用したビューオブジェクトの作成
ビューを作成するには、Interface Builderを使用して視覚的に組み立てる方法が最も簡単です。Interface
Builderでは、ビューをインターフェイスに追加して、これらのビューを階層にまとめることができま
す。また、各ビューの設定を調整し、ビューに関連する動作をコードに関係付けることもできます。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
36
ビュー
ビューオブジェクトの作成と設定
Interface Builderは実際に有効なビューオブジェクト(ビュークラスの実際のインスタンス)を使用す
るため、設計時に表示される内容は実行時の結果と同じになります。続いて、これらの有効なオブ
ジェクトをnibファイルに保存します。このファイルは、オブジェクトの状態と設定を保存するリソー
スファイルです。
通常は、アプリケーションのいずれかのビューコントローラのビュー階層全体を保存するために、nib
ファイルを作成します。nibファイルの最上位には、通常ビューコントローラのビューを表すビュー
オブジェクトが1つ含まれます(ビューコントローラ自体は、一般的にFile's Ownerオブジェクトによっ
て表されます)。最上位のビューは、ターゲットデバイスに合わせて適切にサイズ設定され、表示さ
れるほかのビューをすべて含みます。ビューコントローラのビュー階層の一部だけを保存するために
nibファイルを使用することは、ほとんどありません。
ビューコントローラでnibファイルを使用するときに必要な処理は、nibファイルの情報を使用して
ビューコントローラを初期化することだけです。ビューコントローラは、ビューのロードとアンロー
ドを適切なタイミングで処理します。ただし、nibファイルがビューコントローラに関連付けられて
いない場合は、NSBundleまたはUINibオブジェクトを使用して、nibファイルの内容を手動でロード
できます。これらのオブジェクトは、nibファイルのデータを使用してビューオブジェクトを再編成
します。
Interface Builderを使用してビューを作成および設定する方法については、『InterfaceBuilderUserGuide 』
を参照してください。関連付けられたnibファイルをビューコントローラがロードおよび管理する方
法については、『View Controller Programming Guide for iOS 』の「Creating Custom Content View
Controllers」を参照してください。プログラムでビューをnibファイルをからロードする方法について
は、『Resource Programming Guide 』の「Nib Files」を参照してください。
プログラムによるビューオブジェクトの作成
ビューをプログラムで作成する場合は、標準的な割り当てと初期化のパターンを使用します。ビュー
のデフォルトの初期メソッドはinitWithFrame:メソッドです。このメソッドは、ビューの初期サイ
ズと位置を(すぐ後に設定される)親ビューを基準に設定します。たとえば、新しい汎用のUIView
オブジェクトを作成する場合は、以下のようなコードを使用します。
CGRect
viewRect = CGRectMake(0, 0, 100, 100);
UIView* myView = [[UIView alloc] initWithFrame:viewRect];
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
37
ビュー
ビューオブジェクトの作成と設定
注意: すべてのビューはinitWithFrame:メソッドをサポートしますが、一部のビューには
優先される初期化メソッドがあり、この場合は優先メソッドを使用する必要があります。カ
スタム初期化メソッドの詳細については、対象のクラスのリファレンスドキュメントを参照
してください。
作成したビューを表示するには、そのビューをウインドウ(または、ウインドウ内の別のビュー)に
追加する必要があります。ビューをビュー階層に追加する方法については、“サブビューの追加と削
除” (41 ページ)を参照してください。
ビューのプロパティの設定
UIViewクラスには、ビューの外観や動作を制御する宣言済みプロパティがあります。これらのプロ
パティは、ビューのサイズと位置、ビューの透明度、背景色、およびレンダリングの動作を操作する
ためのものです。これらのプロパティはすべてデフォルト値を持ち、必要に応じて後から変更できま
す。これらのプロパティの多くは、インスペクタウインドウを使用してInterface Builderから設定する
こともできます。
表 3-1に、一般的に使用されるプロパティ(およびメソッド)とその使用方法を示します。ビューの
特定の面について制御できる内容を確認できるように、関連のあるプロパティを並べて示していま
す。
表 3-1
主なビューのプロパティの使用方法
プロパティ
用途
alpha、hidden、opaque
これらのプロパティはビューの透明度に影響します。alphaお
よびhiddenプロパティは、ビューの透明度を直接変更します。
opaqueプロパティは、ビューを合成する方法をシステムに指示
します。ビューのコンテンツが完全に不透明で、これより下に
あるビューのコンテンツを何も表示しない場合は、このプロパ
ティをYESに設定します。このプロパティをYESに設定すると、
不要な合成操作が実行されないためパフォーマンスが向上しま
す。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
38
ビュー
ビューオブジェクトの作成と設定
プロパティ
用途
bounds、frame、center、
transform
これらのプロパティはビューのサイズと位置に影響します。
centerおよびframeプロパティは、ビューの位置を親ビューを
基準に表します。frameには、ビューのサイズも含まれます。
boundsプロパティは、ビューに表示するコンテンツ領域を独自
の座標系で定義します。
transformプロパティは、ビュー全体の複雑なアニメーション
化または移動に使用されます。たとえば、ビューを回転または
拡大縮小するにはtransformによる変換を使用します。現在の変
換が恒等変換でない場合、frameプロパティは未定義となり、
無視する必要があります。
bounds、frame、およびcenterプロパティの関係については、
“frame、bounds、およびcenterプロパティの関係” (16 ページ)
を参照してください。ビューに対する変換の影響については、
“座標系の変換” (17 ページ)を参照してください。
autoresizingMask、
autoresizesSubviews
これらのプロパティは、ビューとそのサブビューの自動サイズ
変更の動作に影響します。autoresizingMaskプロパティは、
親ビューの境界が変更されたときのビューの動作を制御します。
autoresizesSubviewsプロパティは、現在のビューのサブビュー
をサイズ変更するかどうかを制御します。
contentMode、
contentStretch、
contentScaleFactor
これらのプロパティは、ビュー内部でのコンテンツのレンダリ
ング動作に影響します。contentModeおよびcontentStretchプ
ロパティは、ビューの幅または高さが変更されたときのコンテ
ンツの処理方法を決定します。contentScaleFactorプロパティ
は、高解像度の画面のビューの描画動作をカスタマイズする必
要がある場合にだけ使用します。
ビューに対するコンテンツモードの影響については、“コンテン
ツモード” (13 ページ)を参照してください。ビューに対する
コンテンツの引き延ばし矩形の影響については、“引き延ばし可
能なビュー” (13 ページ)を参照してください。拡大縮小につ
いては、『Drawing and Printing Guide for iOS 』の「Supporting
High-Resolution Screens In Views」を参照してください。
gestureRecognizers、
userInteractionEnabled、
multipleTouchEnabled、
exclusiveTouch
これらのプロパティは、ビューがタッチイベントを処理する方
法に影響します。gestureRecognizersプロパティには、ビュー
にアタッチするジェスチャリコグナイザが含まれます。その他
のプロパティは、ビューでサポートされるタッチイベントを制
御します。
ビューでイベントに応答する方法については、『Event Handling
Guide for iOS 』を参照してください。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
39
ビュー
ビュー階層の作成と管理
プロパティ
用途
backgroundColor、
subviews、drawRect:メ
ソッド、layer
(layerClassメソッド)
これらのプロパティとメソッドは、ビューの実際のコンテンツ
を管理するのに役立ちます。簡単なビューでは、背景色を設定
し、1つ以上のサブビューを追加できます。subviewsプロパティ
自体にサブビューの読み出し専用のリストが含まれますが、サ
ブビューを追加および再配置するためのメソッドがいくつかあ
ります。カスタム描画を行うビューでは、drawRect:メソッド
をオーバーライドする必要があります。
より高度なコンテンツでは、ビューのCore Animationのlayerを
直接操作できます。ビューにタイプがまったく異なるレイヤを
指定するには、layerClassメソッドをオーバーライドする必要
があります。
すべてのビューに共通の基本的なプロパティについては、『UIView Class Reference 』を参照してくだ
さい。ビューに固有のプロパティについては、各ビューのリファレンスドキュメントを参照してくだ
さい。
タグによるビューの識別
UIViewクラスに含まれるtagプロパティを使用して、個々のビューオブジェクトに整数値のタグを設
定できます。タグを使用することで、ビュー階層内でビューを一意に識別し、実行時にこれらのビュー
を検索することができます(タグベースの検索は、ビュー階層を反復的に検索するよりも高速です)。
tagプロパティのデフォルト値は0です。
タグを付けたビューを検索するには、viewWithTag:のUIViewメソッドを使用します。このメソッド
は、レシーバーとそのサブビューを深さ優先で検索します。スーパービューやビュー階層のほかの部
分は検索しません。したがって、このメソッドを階層のルートビューから呼び出すと、階層内のすべ
てのビューが検索対象になりますが、特定のサブビューから呼び出した場合は、ビューのサブセット
のみが検索対象となります。
ビュー階層の作成と管理
ビュー階層の管理は、アプリケーションのユーザインターフェイスを開発する上で重要な部分です。
ビューの編成は、アプリケーションの外観と、変更やイベントに対するアプリケーションの動作の両
方に影響します。たとえば、特定のタッチイベントを処理するオブジェクトは、ビュー階層における
親子関係によって決定されます。同様に、インターフェイスの向きが変更されたときの各ビューの動
作も、親子関係によって定義されます。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
40
ビュー
ビュー階層の作成と管理
図 3-1に、ビューを階層化してアプリケーションで目的の視覚効果を得る方法の例を示します。「時
計(Clock)」アプリケーションの場合、ビュー階層に機能の異なるビューが混在しています。タブバー
とナビゲーションのビューは、タブバーコントローラおよびナビゲーションコントローラオブジェク
トで提供される特殊なビュー階層で、それぞれユーザインターフェイスの一部分を管理します。これ
らのバーの間にあるものはすべて、「時計(Clock)」アプリケーションが提供するカスタムビュー階層
に属しています。
図 3-1
「時計(Clock)」アプリケーションにおけるビューの階層化
iOSアプリケーションのビュー階層は、Interface Builderを使用して視覚的に作成したり、コード内でプ
ログラムによって作成するなど、さまざまな方法で構築できます。以降のセクションでは、ビュー階
層を構築する方法、および構築したビュー階層でビューを検索して別のビュー座標系に変換する方法
について説明します。
サブビューの追加と削除
Interface Builderを使用すると、ビュー階層を最も簡単に構築できます。Interface Builderでは、ビュー
を視覚的に整理し、ビュー間の関係を確認して、実行時にビューがどのように表示されるかを正確に
確認できます。Interface Builderを使用する場合は、作成したビュー階層をnibファイルに保存し、実行
時に対応するビューが必要になったときに、このファイルをロードします。
ビューをプログラムで作成する場合は、ビューを作成して初期化した後に、以下のメソッドを使用し
てビューを階層に配置します。
●
●
●
●
サブビューを親に追加する場合は、親ビューのaddSubview:メソッドを呼び出します。このメ
ソッドは、親のサブビューのリストの末尾にサブビューを追加します。
親のサブビューのリストの中間にサブビューを挿入する場合は、親ビューのinsertSubview:...
メソッドのいずれかを呼び出します。リストの中間に挿入したサブビューは、リストでそれより
後にあるビューの背面に配置されます。
既存のサブビューを親ビュー内で並べ替える場合は、親ビューのbringSubviewToFront:、
sendSubviewToBack:、またはexchangeSubviewAtIndex:withSubviewAtIndex:メソッドを呼
び出します。これらのメソッドは、サブビューを削除して再度挿入するよりも高速です。
サブビューを親ビューから削除する場合は、サブビューのremoveFromSuperviewメソッドを呼び
出します(親ビューのメソッドではありません)。
サブビューを親に追加する場合、サブビューの現在のフレーム矩形は親ビュー内での初期位置を示し
ます。フレームがスーパービューの表示境界より外にあるサブビューは、デフォルトでは境界に合わ
せて切り取られません。サブビューをスーパービューの境界に合わせて切り取る場合は、スーパー
ビューのclipsToBoundsプロパティを明示的にYESに設定する必要があります。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
41
ビュー
ビュー階層の作成と管理
ほとんどのアプリケーションにあるapplication:didFinishLaunchingWithOptions:メソッドは、
サブビューを別のビューに追加する最も一般的な例です。リスト 3-1では、このメソッドがアプリケー
ションのメインビューコントローラからアプリケーションウインドウにビューを追加しています。ウ
インドウとビューコントローラはどちらもアプリケーションのメインnibファイルに格納され、この
ファイルはメソッドが呼び出される前にロードされます。ただし、ビューコントローラで管理される
ビュー階層は、viewプロパティが呼び出されるまで実際にはロードされません。
リスト 3-1
ウインドウへのビューの追加
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
// Add the view controller's view to the window and display.
[window addSubview:viewController.view];
[window makeKeyAndVisible];
return YES;
}
サブビューをビュー階層に追加する一般的な方法としては、そのほかにビューコントローラのloadView
またはviewDidLoadメソッドがあります。ビューをプログラムで構築している場合は、ビューの作成
コードをビューコントローラのloadViewメソッドに記述します。ビューをプログラムで作成するか
nibファイルからロードするかにかかわらず、viewDidLoadメソッドにはビューの設定コードを追加
できます。
リスト 3-2に、『UICatalog 』のサンプルアプリケーションで使用されている
TransitionsViewControllerクラスのviewDidLoadメソッドを示します。
TransitionsViewControllerクラスは、2つのビュー間のトランジションに関するアニメーションを
管理します。アプリケーションの(ルートビューとツールバーで構成される)初期ビュー階層は、nib
ファイルからロードされます。続いて、viewDidLoadメソッドのコードが、トランジションを管理す
るためのContainer Viewと画像ビューを作成します。Container Viewの目的は、2つの画像ビューの間の
トランジションアニメーションを実装するために必要なコードを簡素化することです。Container View
自体は、実際のコンテンツを持ちません。
リスト 3-2
既存のビュー階層へのビューの追加
- (void)viewDidLoad
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
42
ビュー
ビュー階層の作成と管理
{
[super viewDidLoad];
self.title = NSLocalizedString(@"TransitionsTitle", @"");
// create the container view which we will use for transition animation (centered
horizontally)
CGRect frame = CGRectMake(round((self.view.bounds.size.width - kImageWidth) /
2.0),
kTopPlacement, kImageWidth,
kImageHeight);
self.containerView = [[[UIView alloc] initWithFrame:frame] autorelease];
[self.view addSubview:self.containerView];
// The container view can represent the images for accessibility.
[self.containerView setIsAccessibilityElement:YES];
[self.containerView setAccessibilityLabel:NSLocalizedString(@"ImagesTitle",
@"")];
// create the initial image view
frame = CGRectMake(0.0, 0.0, kImageWidth, kImageHeight);
self.mainView = [[[UIImageView alloc] initWithFrame:frame] autorelease];
self.mainView.image = [UIImage imageNamed:@"scene1.jpg"];
[self.containerView addSubview:self.mainView];
// create the alternate image view (to transition between)
CGRect imageFrame = CGRectMake(0.0, 0.0, kImageWidth, kImageHeight);
self.flipToView = [[[UIImageView alloc] initWithFrame:imageFrame] autorelease];
self.flipToView.image = [UIImage imageNamed:@"scene2.jpg"];
}
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
43
ビュー
ビュー階層の作成と管理
Important: スーパービューは自動的にサブビューを保持します。したがって、サブビューを埋め
込んだ後は、そのサブビューを解放しても安全です。実際に、アプリケーションがビューを過剰
に保持して後でメモリリークが発生するのを避けるために、サブビューを解放することをお勧め
します。ただし、サブビューをスーパービューから削除した後に再利用する予定の場合は、サブ
ビューを再度保持する必要があることに注意してください。removeFromSuperviewメソッドは、
サブビューをスーパービューから削除する前に、サブビューを自動的に解放します。次のイベン
トループサイクルまでにビューを保持しない場合は、ビューが解放されます。
Cocoaのメモリ管理方法については、『Advanced Memory Management Programming Guide 』を参照
してください。
サブビューを別のビューに追加するときに、UIKitは親ビューと子ビューの両方に変更を通知します。
カスタムビューを実装する場合は、willMoveToSuperview:、willMoveToWindow:、
willRemoveSubview:、didAddSubview:、didMoveToSuperview、またはdidMoveToWindowメソッ
ドの1つ以上をオーバーライドすることで、これらの通知をインターセプトできます。これらの通知
を使用して、ビュー階層に関する状態情報を更新したり、追加タスクを実行することができます。
作成したビュー階層は、ビューのsuperviewおよびsubviewsプロパティを使用してプログラムでナ
ビゲートすることができます。各ビューのwindowプロパティには、ビューが現在表示されているウ
インドウが含まれます(存在する場合)。ビュー階層のルートビューには親がないため、ルートビュー
のsuperviewプロパティはnilに設定されます。現在画面に表示されているビューの場合は、ウイン
ドウオブジェクトがビュー階層のルートビューです。
ビューの非表示
ビューを非表示にするには、hiddenプロパティをYESに設定するか、alphaプロパティを0.0に変更
します。非表示のビューは、システムからタッチイベントを受信しません。ただし、ビュー階層に関
する自動サイズ変更とその他のレイアウト操作は、非表示のビューにも関係します。したがって、特
にビューを後でもう一度表示する予定の場合、通常はビュー階層からビューを削除する代わりにビュー
を非表示にする方が便利です。
Important: 現在ファーストレスポンダになっているビューを非表示にする場合、ビューはファー
ストレスポンダの状態を自動的に放棄しません。ファーストレスポンダをターゲットにしたイベ
ントは、非表示にしたビューにこれまでどおり送信されます。これを避けるには、ビューを非表
示にするときにファーストレスポンダの状態を強制的に放棄させます。これらのレスポンダチェー
ンの詳細については、『Event Handling Guide for iOS 』を参照してください。
ビューのトランジションを表示から非表示(またはその逆)にアニメーション化する場合は、ビュー
のalphaプロパティを使用する必要があります。hiddenプロパティはアニメーション化可能なプロパ
ティではありません。したがって、変更した設定はただちに有効になります。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
44
ビュー
ビュー階層の作成と管理
ビュー階層でのビューの検索
ビュー階層でビューを検索するには、2つの方法があります。
●
●
関連するビューへのポインタを適切な場所(ビューを所有するビューコントローラなど)に保存
します。
各ビューのtagプロパティに一意の整数値を割り当て、viewWithTag:メソッドを使用して検索し
ます。
関連するビューの参照の保存は、ビューを検索する最も一般的な方法で、ビューにアクセスする場合
に便利です。Interface Builderを使用してビューを作成した場合は、アウトレットを使用して、nibファ
イルのオブジェクト(管理用のコントローラオブジェクトを表すFile's Ownerオブジェクトを含む)を
別のオブジェクトに接続できます。プログラムで作成するビューでは、ビューへの参照をプライベー
トなメンバー変数に保存できます。アウトレットまたはプライベートなメンバー変数のどちらを使用
する場合でも、デベロッパは必要に応じてビューを保持し、その後でビューを解放する必要がありま
す。オブジェクトの保持と解放を適切に行うには、宣言済みプロパティを使用するのが最善の方法で
す。
タグは、ハードコードされた依存関係を減らす有効な方法で、より動的で柔軟なソリューションをサ
ポートします。ビューへのポインタを保存する代わりに、タグを使用してビューを検索できます。タ
グは、ビューの参照方法としてより永続的でもあります。たとえば、現在アプリケーションに表示し
ているビューのリストを保存する場合は、表示している各ビューのタグをファイルに書き出します。
この方法は、実際のビューオブジェクトをアーカイブするよりも簡単です。特に、現在表示している
ビューを追跡しているだけの場合に有効な方法です。アプリケーションが後でロードされるときに、
ビューを再作成し、保存したタグのリストを使用して各ビューの表示設定を行うことで、ビュー階層
は以前の状態に戻ります。
ビューの平行移動、拡大縮小、回転
すべてのビューには、ビューのコンテンツを平行移動、拡大縮小、または回転するために使用でき
る、アフィン変換が関連付けられています。ビューの変換は、レンダリングされたビューの最終的な
外観を変更し、多くの場合はスクロール、アニメーション、またはその他の視覚効果を実装するため
に使用されます。
UIViewのtransformプロパティには、適用する変換を表すCGAffineTransform構造体が含まれます。
デフォルトでは、このプロパティはビューの外観を変更しない恒等変換に設定されます。このプロパ
ティには、いつでも新しい変換を割り当てることができます。たとえば、ビューを45度回転させるに
は、以下のコードを使用できます。
// M_PI/4.0 is one quarter of a half circle, or 45 degrees.
CGAffineTransform xform = CGAffineTransformMakeRotation(M_PI/4.0);
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
45
ビュー
ビュー階層の作成と管理
self.view.transform = xform;
上のコードでビューに変換を適用すると、ビューが中心点を基準に時計回りに回転されます。図 3-2
は、この変換をアプリケーションに埋め込まれた画像ビューに適用した場合の様子を示しています。
図 3-2
ビューの45度回転
1つのビューに複数の変換を適用する場合は、変換をCGAffineTransform構造体に追加する順序が重
要になります。ビューを回転してから平行移動するのは、ビューを平行移動してから回転するのと同
じではありません。回転と平行移動の量がそれぞれ同じでも、一連の変換が最終結果に影響します。
また、追加する変換はいずれも、ビューの中心点を基準にして適用されます。したがって、回転を適
用すると、ビューは中心点を基準にして回転します。ビューを拡大縮小すると、ビューの幅と高さは
変わりますが、中心点は変わりません。
アフィン変換の作成と使用方法については、『Quartz 2D Programming Guide 』の「Transforms」を参
照してください。
ビュー階層での座標の変換
さまざまな状況で(特にイベントを処理する場合に)、アプリケーションでは座標値を異なる座標系
の間で変換する必要が生じます。たとえば、タッチイベントは各タッチの位置をウインドウの座標系
で報告しますが、多くの場合、ビューオブジェクトではビューのローカル座標系に基づいた情報が必
要となります。UIViewクラスには、座標をビューのローカル座標系との間で変換するための、以下
のメソッドが定義されています。
convertPoint:fromView:
convertRect:fromView:
convertPoint:toView:
convertRect:toView:
convert...:fromView:メソッドは、座標を別のビューの座標系から現在のビューのローカル座標系
(境界矩形)に変換します。convert...:toView:メソッドは、これとは逆に、座標を現在のビュー
の座標系(境界矩形)から指定したビューの座標系に変換します。いずれのメソッドでも参照ビュー
にnilを指定すると、ビューを含んでいるウインドウの座標系との間で座標が変換されます。
UIViewの変換メソッドのほかに、UIWindowクラスでもいくつかの変換メソッドが定義されています。
これらのメソッドはUIViewのメソッドとほぼ同じですが、ビューのローカル座標系との間で変換を
行う代わりに、ウインドウの座標系との間で変換を行います。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
46
ビュー
実行時のビューのサイズと位置の調整
convertPoint:fromWindow:
convertRect:fromWindow:
convertPoint:toWindow:
convertRect:toWindow:
回転されたビューの座標を変換する場合、UIKitは変換された矩形が元の矩形の占める画面領域を反映
するように変換を行います。図 3-3に、回転によって変換中に矩形のサイズが変更される例を示しま
す。図では、外側の親ビューに回転されたサブビューが含まれています。サブビューの座標系にある
矩形を親の座標系に変換すると、矩形が物理的に大きくなります。この大きい矩形は、outerViewの
境界内の、回転された矩形が完全に収まる最小の矩形です。
図 3-3
回転したビューの値の変換
実行時のビューのサイズと位置の調整
ビューのサイズを変更する場合は、それに合わせて必ずサブビューのサイズと位置を変更する必要が
あります。UIViewクラスは、ビュー階層におけるビューの自動レイアウトおよび手動レイアウトの
両方をサポートします。自動レイアウトでは、親ビューがサイズ変更されたときに各ビューが従うべ
き規則を設定し、その他のサイズ変更の操作は必要ありません。手動レイアウトでは、ビューのサイ
ズと位置を必要に応じて調整します。
レイアウト変更への備え
レイアウトの変更は、ビューで以下のイベントが発生したときに常に起こります。
●
●
●
●
●
ビューの境界矩形のサイズが変更される。
インターフェイスの向きの変更が発生する。通常はルートビューの境界矩形の変更がトリガされ
ます。
ビューのレイヤに関連付けられたCore Animationサブレイヤのセットが変更され、レイアウト変
更を必要としている。
アプリケーションがビューのsetNeedsLayoutまたはlayoutIfNeededメソッドを呼び出して、強
制的にレイアウト変更を行う。
アプリケーションがビューの下位レベルのレイヤオブジェクトのsetNeedsLayoutメソッドを呼
び出して、強制的にレイアウト変更を行う。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
47
ビュー
実行時のビューのサイズと位置の調整
自動サイズ変更規則を使用した自動的なレイアウト変更の処理
ビューのサイズを変更する場合、通常は埋め込まれているサブビューの位置とサイズを親の新しいサ
イズに合わせて変更する必要があります。スーパービューのautoresizesSubviewsプロパティは、
サブビューをサイズ変更するかどうかを決定します。このプロパティをYESに設定すると、ビューは
各サブビューのautoresizingMaskプロパティを使用して、サブビューのサイズと位置を設定する方
法を決定します。サブビューに対するサイズ変更は、埋め込まれているサブビューに対して同様のレ
イアウト調整をトリガします。
ビュー階層のビューごとに、そのビューのautoresizingMaskプロパティを適切な値に設定すること
は、自動レイアウト変更の処理において重要です。表 3-2に、ビューに適用できる自動サイズ変更オ
プションと、レイアウト処理におけるそれぞれの効果を示します。autoresizingMaskプロパティに
定数を割り当てる前に、OR演算子を使用して定数を結合したり、単純に加算することができます。
Interface Builderを使用してビューを構築している場合は、「Autosizing」インスペクタを使用して、こ
れらのプロパティを設定できます。
表 3-2
自動サイズ変更マスク定数
自動サイズ変更マスク
解説
UIViewAutoresizingNone
ビューは自動サイズ変更されません(これがデフォルト値です)。
UIViewAutoresizingFlexibleHeight
スーパービューの高さが変更されたときに、ビューの高さが変更
されます。この定数が含まれていない場合、ビューの高さは変更
されません。
UIViewAutoresizingFlexibleWidth
スーパービューの幅が変更されたときに、ビューの幅が変更され
ます。この定数が含まれていない場合、ビューの幅は変更されま
せん。
UIViewAutoresizingFlexibleLeftMargin
ビューの左端からスーパービューの左端までの距離が、必要に応
じて増減されます。この定数が含まれていない場合は、スーパー
ビューの左端からビューの左端までの距離が固定されます。
UIViewAutoresizingFlexibleRightMargin
ビューの右端からスーパービューの右端までの距離が、必要に応
じて増減されます。この定数が含まれていない場合は、スーパー
ビューの右端からビューの右端までの距離が固定されます。
UIViewAutoresizingFlexibleBottomMargin
ビューの下端からスーパービューの下端までの距離が、必要に応
じて増減されます。この定数が含まれていない場合は、スーパー
ビューの下端からビューの下端までの距離が固定されます。
UIViewAutoresizingFlexibleTopMargin
ビューの上端からスーパービューの上端までの距離が、必要に応
じて増減されます。この定数が含まれていない場合は、スーパー
ビューの上端からビューの上端までの距離が固定されます。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
48
ビュー
実行時のビューのサイズと位置の調整
図 3-4は、自動サイズ変更マスクのオプションがビューに適用される様子を示しています。各定数が
指定されている場合は、ビューの指定された部分がサイズ変更可能で、スーパービューの境界が変更
されたときに変更可能であることを示します。定数が指定されていない場合は、ビューのレイアウト
がその部分について固定であることを示します。1つの軸に対してサイズ変更可能な属性が2つ以上あ
るビューを設定する場合、UIKitは対応する空間にサイズ変更を均等に配分します。
図 3-4
ビューの自動サイズ変更マスク定数
自動サイズ変更規則を設定するには、Interface Builderの「Size」インスペクタにある「Autosizing」の
コントロールを使用するのが最も簡単です。上の図のサイズ変更可能な幅と高さの定数は、
「Autosizing」コントロールに表示される幅と高さのインジケータと同じ動作を行います。ただし、
マージンに関するインジケータの動作と使用法は、実際には逆になります。Interface Builderでは、
マージンインジケータが設定されているとマージンが固定サイズとなり、インジケータが設定されて
いない場合はマージンがサイズ変更可能になります。Interface Builderでは、自動サイズ変更の動作を
変更するとビューにどのように影響するかがアニメーションで示されます。
Important: ビューのtransformプロパティに恒等変換が含まれていない場合、そのビューのフレー
ムは未定義となり、自動サイズ変更の動作も未定義となります。
影響を受けるすべてのビューに対して自動サイズ変更規則が適用された後、UIKitは各ビューにおい
て、スーパービューに対する手動の調整を実行できるようにします。ビューのレイアウトを手動で管
理する方法については、“手動によるビューのレイアウトの調整” (49 ページ)を参照してください。
手動によるビューのレイアウトの調整
ビューのサイズが変更されると、UIKitはビューのサブビューに自動サイズ変更を適用した後、ビュー
のlayoutSubviewsメソッドを呼び出して、手動による変更を実行できるようにします。自動サイズ
変更による動作だけでは希望する結果が得られない場合は、カスタムビューでlayoutSubviewsメソッ
ドを実装できます。このメソッドの実装では、以下の処理を実行できます。
●
直下のサブビューのサイズと位置を調整する。
●
サブビューまたはCore Animationレイヤを追加または削除する。
●
サブビューのsetNeedsDisplayまたはsetNeedsDisplayInRect:メソッドを呼び出して、サブ
ビューを強制的に再描画する。
アプリケーションがサブビューを手動で配置する例としては、大きなスクロール可能領域を実装する
場合があります。スクロール可能なコンテンツのために1つの大きなビューを使用することは現実的
ではないため、多くの場合、アプリケーションは多数の小さいタイル状のビューを含むルートビュー
を実装します。各タイルは、スクロール可能なコンテンツの一部分を表します。スクロールイベント
が発生すると、ルートビューはsetNeedsLayoutメソッドを呼び出して、レイアウトの変更を開始し
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
49
ビュー
実行時のビューの変更
ます。続いて、layoutSubviewsメソッドが、発生したスクロール量に基づいてタイル状のビューを
再配置します。タイルがビューの表示領域からスクロールアウトすると、layoutSubviewsメソッド
はタイルをスクロールインする側の端に移動し、その過程でタイルのコンテンツを置き換えます。
レイアウトコードを作成するときには、以下の方法でコードをテストしてください。
●
●
ビューの向きを変更したときに、サポートされるすべてのインターフェイスの向きに対してレイ
アウトが正しく表示されることを確認します。
ステータスバーの高さを変更したときに、コードが適切に応答することを確認します。通話中は
ステータスバーの高さのサイズが大きくなり、ユーザが通話を終了するとステータスバーのサイ
ズは小さくなります。
自動サイズ変更の動作がビューのサイズと位置にどのように影響するかについては、“自動サイズ変
更規則を使用した自動的なレイアウト変更の処理” (48 ページ)を参照してください。タイル処理の
実装例については、『ScrollViewSuite 』のサンプルの例を参照してください。
実行時のビューの変更
アプリケーションはユーザから入力を受け取ると、入力に応じてユーザインターフェイスを調整しま
す。アプリケーションは、ビューの再配置、ビューのサイズまたは位置の変更、ビューの表示と非表
示の切り替え、または完全に新しいビューセットのロードによってビューを変更します。iOSアプリ
ケーションでは、以下のさまざまな場所と場所でこれらの操作を実行します。
●
ビューコントローラ:
●
●
●
●
ビューコントローラは、表示する前にビューを作成する必要があります。ビューをnibファイ
ルからロードするか、プログラムで作成できます。ビューが不要になったら、これらのビュー
を破棄します。
デバイスの向きが変更されると、ビューコントローラはビューのサイズと位置を変更に合わ
せて調整します。新しい向きへの調整の一部として、一部のビューを非表示にしたり、別の
ビューを表示する場合もあります。
ビューコントローラが編集可能なコンテンツを管理する場合は、編集モードへの移行時およ
び編集モードの終了時にビュー階層を調整することがあります。たとえば、さまざまなコン
テンツの編集を容易にするために、ボタンやコントロールを追加する場合があります。この
とき、追加されるコントロールに合わせて、既存のビューのサイズ変更が必要になる場合も
あります。
アニメーションブロック:
●
ユーザインターフェイスでビューセット間のトランジションを行う場合は、アニメーション
ブロック内で一方のビューを非表示にし、もう一方のビューを表示します。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
50
ビュー
Core Animationレイヤとのやり取り
●
●
特殊効果を実装する場合は、アニメーションブロックを使用してビューの各種プロパティを
変更します。たとえば、ビューのサイズ変更をアニメーション化する場合は、フレーム矩形
のサイズを変更します。
その他の方法:
●
●
●
タッチイベントやジェスチャが発生したときに、ユーザインターフェイスは新しいビューセッ
トをロードしたり、現在のビューセットを変更することで応答します。イベントの処理につ
いては、『Event Handling Guide for iOS 』を参照してください。
ユーザがスクロールビューを操作する場合は、スクロール可能な大きな領域でタイル状のサ
ブビューの表示と非表示を切り替えます。スクロール可能なコンテンツの詳細については、
『Scroll View Programming Guide for iOS 』を参照してください。
キーボードを表示するときには、キーボードに隠れないようにビューを再配置またはサイズ
変更します。キーボードとやり取りを行う方法については、『Text,Web,andEditingProgramming
Guide for iOS 』を参照してください。
ビューに対する変更を開始する場所としては、ビューコントローラが一般的です。ビューコントロー
ラは表示されているコンテンツに関連付けられたビュー階層を管理するため、これらのビューで発生
する処理は最終的にすべてビューコントローラが実行します。ビューをロードするとき、または向き
の変更を処理するときに、ビューコントローラは新しいビューの追加や、既存のビューの非表示また
は置換を行ったり、ビューの表示準備のための変更を必要なだけ実行することができます。ビューの
コンテンツを編集するためのサポートを実装する場合は、UIViewControllerのsetEditing:animated:
メソッドで、ビューを編集可能なバージョンに切り替えたり、元に戻したりすることができます。
アニメーションブロックも、ビューに関する変更を開始する一般的な場所です。UIViewクラスに組
み込まれたアニメーションのサポートにより、ビューのプロパティに対する変更を簡単にアニメー
ション化することができます。transitionWithView:duration:options:animations:completion:
またはtransitionFromView:toView:duration:options:completion:メソッドを使用して、ビュー
セット全体を別のセットに入れ替えることもできます。
ビューのアニメーション化とビューのトランジションの開始については、“アニメーション” (60 ペー
ジ)を参照してください。ビューコントローラを使用してビューに関する動作を管理する方法につい
ては、『View Controller Programming Guide for iOS 』を参照してください。
Core Animationレイヤとのやり取り
各ビューオブジェクトは、画面上でビューのコンテンツの表示とアニメーションを管理する、専用の
Core Animationレイヤを持ちます。ビューオブジェクトでもさまざまな処理を実行できますが、必要
な場合は対応するレイヤオブジェクトを直接操作することもできます。ビューのレイヤオブジェクト
は、ビューのlayerプロパティに保存されます。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
51
ビュー
Core Animationレイヤとのやり取り
ビューに関連付けられたレイヤクラスの変更
ビューを作成した後に、ビューに関連付けられたレイヤのタイプを変更することはできません。した
がって、各ビューはlayerClassクラスメソッドを使用して、レイヤオブジェクトのクラスを指定し
ます。このメソッドのデフォルトの実装はCALayerクラスを返します。この値を変更するには、サブ
クラス化してメソッドをオーバーライドし、別の値を返す以外に方法はありません。この値を変更し
て、別の種類のレイヤを使うことができます。たとえば、ビューが大きなスクロール可能領域を表示
するためにタイル処理を使用している場合、ビューの背景としてCATiledLayerクラスを使うとよい
かも知れません。
layerClassメソッドの実装では、単純に目的のClassオブジェクトを作成して、これを返すだけにし
ます。たとえば、タイリングを行うビューでは、このメソッドを次のように実装します。
+ (Class)layerClass
{
return [CATiledLayer class];
}
各ビューは、初期化プロセスの早期にlayerClassメソッドを呼び出し、返されたクラスを使用して
レイヤオブジェクトを作成します。また、ビューは常に自身をレイヤオブジェクトのデリゲートとし
て割り当てます。この時点で、ビューはレイヤを所有し、ビューとレイヤの関係を変更できなくなり
ます。同じビューを、別のレイヤオブジェクトのデリゲートとして割り当てることもできません。
ビューの所有またはデリゲートの関係を変更すると、描画の問題が発生し、アプリケーションがク
ラッシュする可能性があります。
Core Animationで提供されるレイヤオブジェクトのタイプについては、『Core Animation Reference
Collection 』を参照してください。
ビューへのレイヤオブジェクトの埋め込み
ビューの代わりに主にレイヤオブジェクトを操作する場合は、必要に応じて、カスタムレイヤオブ
ジェクトをビュー階層に組み込むことができます。カスタムレイヤオブジェクトは、ビューによって
所有されないCALayerのインスタンスです。一般的には、カスタムレイヤをプログラムで作成し、
Core Animationのルーチンを使用してこれらを組み込みます。カスタムレイヤはイベントの受信やレ
スポンダチェーンへの参加は行いませんが、自身の描画および親ビューまたはレイヤのサイズ変更へ
の応答をCore Animation規則に従って行います。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
52
ビュー
Core Animationレイヤとのやり取り
リスト 3-3に、ビューコントローラのviewDidLoadメソッドの例を示します。このメソッドは、カス
タムレイヤオブジェクトを作成し、これをルートビューに追加します。レイヤは、アニメーション化
される静止画像を表示するために使用されます。レイヤをビュー自体に追加する代わりに、ビューの
下位レベルのレイヤに追加します。
リスト 3-3
ビューへのカスタムレイヤの追加
- (void)viewDidLoad {
[super viewDidLoad];
// Create the layer.
CALayer* myLayer = [[CALayer alloc] init];
// Set the contents of the layer to a fixed image. And set
// the size of the layer to match the image size.
UIImage layerContents = [[UIImage imageNamed:@"myImage"] retain];
CGSize imageSize = layerContents.size;
myLayer.bounds = CGRectMake(0, 0, imageSize.width, imageSize.height);
myLayer = layerContents.CGImage;
// Add the layer to the view.
CALayer*
viewLayer = self.view.layer;
[viewLayer addSublayer:myLayer];
// Center the layer in the view.
CGRect
viewBounds = backingView.bounds;
myLayer.position = CGPointMake(CGRectGetMidX(viewBounds),
CGRectGetMidY(viewBounds));
// Release the layer, since it is retained by the view's layer
[myLayer release];
}
必要な数のサブレイヤを追加して、サブレイヤ階層にまとめることもできます。ただし、いずれはこ
れらのレイヤをビューのレイヤオブジェクトにアタッチする必要があります。
レイヤを直接操作する方法については、『Core Animation Programming Guide 』を参照してください。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
53
ビュー
カスタムビューの定義
カスタムビューの定義
標準のシステムビューでは必要な動作を実現できない場合は、カスタムビューを定義できます。カス
タムビューを使用すると、アプリケーションのコンテンツの外観およびコンテンツとのやり取りを処
理する方法を完全に制御することができます。
注意: 描画にOpenGL ESを使っている場合、UIViewのサブクラスを定義するのではなく、
GLKViewクラスを使わなければなりません。OpenGL ESで描画する方法について詳しくは、
『OpenGL ES Programming Guide for iOS 』を参照してください。
カスタムビューを実装する際のチェックリスト
カスタムビューの役目は、コンテンツを表示し、そのコンテンツとのやり取りを管理することです。
ただし、カスタムビューを正しく実装するためには、単に描画とイベント処理を行う以上の作業が必
要です。以下のチェックリストには、カスタムビューを実装するときにオーバーライドできる重要な
メソッド(および提供する動作)を示しています。
●
ビューの適切な初期化メソッドを定義します。
●
●
●
●
ビューをプログラムで作成する場合は、initWithFrame:メソッドをオーバーライドするか、
カスタム初期化メソッドを定義します。
ビューをnibファイルからロードする場合は、initWithCoder:メソッドをオーバーライドし
ます。このメソッドを使用して、ビューを初期化し、既知の状態に設定します。
deallocメソッドを実装して、カスタムデータのクリーンアップを処理します。
カスタム描画を処理するには、drawRect:メソッドをオーバーライドして、そこで描画を行いま
す。
●
ビューのautoresizingMaskプロパティを設定して、自動サイズ変更の動作を定義します。
●
ビュークラスが1つ以上のサブビューを管理する場合は、以下の処理を行います。
●
ビューの初期化シーケンス中にこれらのサブビューを作成します。
●
各サブビューのautoresizingMaskプロパティを作成時に設定します。
●
●
サブビューでカスタムレイアウトが必要な場合は、layoutSubviewsメソッドをオーバーラ
イドし、そこでレイアウトコードを実装します。
タッチベースのイベントを処理するには、以下の処理を行います。
●
addGestureRecognizer:メソッドを使用して、適切なジェスチャリコグナイザをビューにア
タッチします。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
54
ビュー
カスタムビューの定義
●
●
タッチを自分で処理する場合は、touchesBegan:withEvent:、touchesMoved:withEvent:、
touchesEnded:withEvent:、およびtouchesCancelled:withEvent:メソッドをオーバーラ
イドします(他にどのタッチ関連のメソッドをオーバーライドするかにかかわらず、
touchesCancelled:withEvent:メソッドは常にオーバーライドが必要であることに注意し
てください)。
ビューを印刷したときに画面上の表示と異なるようにする場合は、
drawRect:forViewPrintFormatter:メソッドを実装します。ビューで印刷をサポートする方法
については、『Drawing and Printing Guide for iOS 』を参照してください。
メソッドのオーバーライドに加え、ビューの既存のプロパティとメソッドを利用してさまざまな処理
を実行できることも覚えておいてください。たとえば、contentModeおよびcontentStretchプロパ
ティを使用すると、レンダリングされたビューの最終的な外観を変更でき、コンテンツを自分で再描
画する場合によく利用されます。UIViewクラス自体に加え、ビューの下位レベルのCALayerオブジェ
クトには、直接または間接的に設定できるさまざまな要素があります。レイヤオブジェクトそのもの
のクラスを変更することさえ可能です。
ビュークラスのメソッドとプロパティについては、『UIView Class Reference 』を参照してください。
カスタムビューの初期化
新規に定義するビューオブジェクトには、それぞれカスタムのinitWithFrame:初期化メソッドを含
める必要があります。このメソッドは、作成時にクラスを初期化し、ビューオブジェクトを既知の状
態に設定します。ビューのインスタンスをコード内でプログラムによって作成する場合は、このメ
ソッドを使用します。
リスト 3-4に、標準的なinitWithFrame:メソッドの実装の骨格を示します。このメソッドは、最初に
メソッドの継承された実装を呼び出します。次に、クラスのインスタンス変数と状態情報を初期化し
た後、初期化されたオブジェクトを返します。継承された実装の呼び出しは、慣例として最初に実行
されます。問題がある場合に独自の初期化コードを終了して、nilを返すことができるようにするた
めです。
リスト 3-4
ビューのサブクラスの初期化
- (id)initWithFrame:(CGRect)aRect {
self = [super initWithFrame:aRect];
if (self) {
// setup the initial properties of the view
...
}
return self;
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
55
ビュー
カスタムビューの定義
}
カスタムビュークラスのインスタンスをnibファイルからロードする場合、iOSではnibをロードする
コードが、新しいビューオブジェクトをインスタンス化するためにinitWithFrame:メソッドを使用
しないことに注意してください。代わりに、NSCodingプロトコルの一部であるinitWithCoder:メ
ソッドを使用します。
ビューがNSCodingプロトコルを採用する場合でも、Interface Builderはビューのカスタムプロパティを
認識していないため、これらのプロパティをnibファイルにエンコードしません。このため、独自の
initWithCoder:メソッドでは、何らかの初期化コードを実行して、ビューを既知の状態に設定する
必要があります。また、ビュークラスでawakeFromNibメソッドを実装し、このメソッドを使用して
その他の初期化を実行することもできます。
描画コードの実装
カスタム描画を行う必要があるビューでは、drawRect:メソッドをオーバーライドし、そこで描画を
行う必要があります。カスタム描画は、最後の手段として使用することをお勧めします。一般的に、
ほかのビューを使用してコンテンツを表示できる場合は、それらのビューを使用してください。
drawRect:メソッドの実装では、コンテンツの描画だけを行ってください。このメソッドは、アプリ
ケーションのデータ構造を更新したり、描画と関係ないタスクを実行する場所ではありません。描画
環境を設定し、コンテンツを描画して、できるだけ早く終了します。drawRect:メソッドが頻繁に呼
び出される場合は、可能な限り描画コードを最適化して、メソッドの各呼び出しで描画する量をでき
るだけ少なくします。
ビューのdrawRect:メソッドを呼び出す前に、UIKitはビューの基本的な描画環境を設定します。具体
的には、グラフィックスコンテキストを作成し、座標系および切り取り領域をビューの座標系および
表示境界に一致するように調整します。したがって、drawRect:メソッドが呼び出されるときには、
UIKitやCore Graphicsなどのネイティブの描画テクノロジーを使用してコンテンツの描画を開始できる
ようになっています。現在のグラフィックスコンテキストのポインタは、
UIGraphicsGetCurrentContext関数を使用して取得できます。
Important: 現在のグラフィックスコンテキストは、ビューのdrawRect:メソッドが呼び出された
ときに、その呼び出しの間だけ有効です。このメソッドがその後呼び出されるごとに、UIKitはそ
れぞれ別のグラフィックスコンテキストを作成します。したがって、オブジェクトをキャッシュ
して後で使用することはできません。
リスト 3-5に、drawRect:メソッドの簡単な実装を示します。この実装では、ビューの周りに幅10ピ
クセルの赤い枠を描画します。UIKitの描画操作は基礎となる実装にCore Graphicsを使用するため、こ
こで示すように描画の呼び出しを混在させても、期待どおりの結果が得られます。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
56
ビュー
カスタムビューの定義
リスト 3-5
描画メソッド
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect
myFrame = self.bounds;
// Set the line width to 10 and inset the rectangle by
// 5 pixels on all sides to compensate for the wider line.
CGContextSetLineWidth(context, 10);
CGRectInset(myFrame, 5, 5);
[[UIColor redColor] set];
UIRectFrame(myFrame);
}
ビューの描画コードが常にビュー全体に不透明なコンテンツを表示することがわかっている場合は、
ビューのopaqueプロパティをYESに設定することで、システムのパフォーマンスを向上させることが
できます。ビューを不透明としてマークすると、UIKitはそのビューのすぐ背後にあるコンテンツの描
画を行いません。これにより、描画にかかる時間が短縮されるだけでなく、ビューをほかのコンテン
ツと合成するために必要な処理も最小化されます。ただし、このプロパティをYESに設定するのは、
ビューのコンテンツが完全に不透明であることが既知である場合のみにしてください。ビューのコン
テンツが常に不透明であることを保証できない場合は、プロパティをNOに設定します。
特にスクロール中の描画パフォーマンスを向上させる方法として、ビューの
clearsContextBeforeDrawingプロパティをNOに設定することもできます。このプロパティがYESに
設定されていると、UIKitはdrawRect:メソッドによって更新される領域を、メソッドが呼び出される
前に自動的に透明な黒色で塗りつぶします。このプロパティをNOに設定すると、この塗りつぶし処理
のオーバーヘッドを回避できますが、drawRect:メソッドに渡される更新矩形一杯にコンテンツを表
示する処理によってアプリケーションに負担がかかります。
イベントへの応答
ビューオブジェクトはレスポンダオブジェクト(UIResponderクラスのインスタンス)であり、タッ
チイベントを受け取ることができます。タッチイベントが発生すると、ウインドウは対応するイベン
トオブジェクトをタッチイベントが発生したビューにディスパッチします。ビューでイベントを処理
しない場合、ビューはこのイベントを無視するか、別のオブジェクトで処理されるようにレスポンダ
チェーンに渡すことができます。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
57
ビュー
カスタムビューの定義
タッチイベントを直接処理するほかに、ビューはジェスチャリコグナイザを使用して、タップ、スワ
イプ、ピンチ、およびその他の一般的なタッチに関するジェスチャを検出できます。ジェスチャリコ
グナイザは、タッチイベントを追跡し、これらが目的のジェスチャとして正しい基準に従っているこ
とを確認するという面倒な処理を担います。アプリケーションでタッチイベントを追跡する代わり
に、ジェスチャリコグナイザを作成し、適切なターゲットオブジェクトとアクションメソッドを割り
当て、addGestureRecognizer:メソッドを使用してビューに組み込むことができます。対応するジェ
スチャが発生すると、ジェスチャリコグナイザがアクションメソッドを呼び出します。
タッチイベントを直接処理する場合は、ビューに以下のメソッドを実装できます。これらのメソッド
については、『Event Handling Guide for iOS 』を参照してください。
touchesBegan:withEvent:
touchesMoved:withEvent:
touchesEnded:withEvent:
touchesCancelled:withEvent:
ビューのデフォルトの動作では、一度に1つのタッチにだけ応答します。ユーザがタッチ中に別の指
を画面に当てても、システムはタッチイベントを無視し、これをビューに報告しません。ビューのイ
ベント処理メソッドから複数の指によるジェスチャを追跡したい場合は、ビューの
multipleTouchEnabledプロパティをYESに設定して、マルチタッチイベントを有効にする必要があ
ります。
ラベルやイメージなどの一部のビューは、初期状態ではイベント処理をすべて無効にします。ビュー
がタッチイベントを受信できるかどうかは、ビューのuserInteractionEnabledプロパティの値を変
更して制御できます。このプロパティを一時的にNOに設定すると、時間のかかる操作を処理している
間に、ユーザがビューのコンテンツを操作するのを防げます。イベントがビューに届かないようにす
るには、UIApplicationオブジェクトのbeginIgnoringInteractionEventsおよび
endIgnoringInteractionEventsメソッドを使用することもできます。これらのメソッドは、1つの
ビューだけでなくアプリケーション全体のイベントの配信に影響を与えます。
注意: UIViewのアニメーションに関するメソッドは、一般的にアニメーションを再生して
いる間のタッチイベントを無効にします。アニメーションを適切に設定することで、この動
作をオーバーライドできます。アニメーションの実行については、“アニメーション” (60 ペー
ジ)を参照してください。
タッチイベントを処理するときに、UIKitはUIViewのhitTest:withEvent:および
pointInside:withEvent:メソッドを使用して、タッチイベントがビューの境界内で発生したかどう
かを判定します。ほとんどの場合、これらのメソッドをオーバーライドする必要はありませんが、
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
58
ビュー
カスタムビューの定義
ビューにカスタムタッチ動作を実装するためにオーバーライドすることもできます。たとえば、これ
らのメソッドをオーバーライドして、サブビューがタッチイベントを処理しないようにすることがで
きます。
ビューを使用した後のクリーンアップ
ビュークラスが、メモリを割り当てたり、カスタムオブジェクトへの参照を格納したり、ビューが解
放されたときに解放しなければならないリソースを保持したりしている場合は、deallocメソッドを
実装する必要があります。ビューの保持カウントが0になり、ビューを解放するタイミングになると、
システムはdeallocメソッドを呼び出します。リスト 3-6に示すように、このメソッドの実装では、
ビューが保持しているオブジェクトまたはリソースを解放してから、継承された実装を呼び出しま
す。このメソッドを使用して、ほかの種類のタスクを実行しないでください。
リスト 3-6
deallocメソッドの実装
- (void)dealloc {
// Release a retained UIColor object
[color release];
// Call the inherited implementation
[super dealloc];
}
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
59
アニメーション
アニメーションは、ユーザインターフェイスをある状態から別の状態へ変更するときに滑らかな視覚
効果を与えます。iOSでは、ビューの再配置、サイズ変更、ビュー階層からの削除、および非表示化
に、数多くのアニメーションが使用されています。ユーザにフィードバックを返したり、関心を引く
ような視覚効果を実装する場合も、アニメーションを使用できます。
iOSでは、複雑なアニメーションを作成するために、描画コードを記述する必要はありません。この
章で説明するすべてのアニメーション技術では、Core Animationで提供される組み込みのサポートを
使用します。デベロッパに必要な処理は、アニメーションをトリガして、Core Animationに各フレー
ムのレンダリングを処理させることだけです。これにより、数行のコードだけで複雑なアニメーショ
ンを簡単に作成できます。
アニメーション化の対象
UIKitとCore Animationはどちらもアニメーションのサポートを提供していますが、それぞれのテクノ
ロジーで提供されるサポートのレベルは異なります。UIKitでは、アニメーションはUIViewオブジェ
クトを使用して実行されます。ビューは、一般的な多くのタスクをカバーする基本的なアニメーショ
ンのセットをサポートします。たとえば、ビューのプロパティの変更をアニメーション化したり、ト
ランジションアニメーションを使用してビューセットを入れ替えることができます。
表 4-1に、UIViewクラスのアニメーション化可能なプロパティ(アニメーションのサポートが組み込
まれているプロパティ)を示します。アニメーション化可能とは、アニメーションが自動的に発生す
るという意味ではありません。これらのプロパティの値を変更すると、通常はプロパティ(および
ビュー)がただちに更新されるだけで、アニメーションは実行されません。これらの変更をアニメー
ション化するには、プロパティの値をアニメーションブロック内で変更する必要があります。これに
ついては、“ビューのプロパティに対する変更のアニメーション化” (62 ページ)で説明します。
表 4-1
アニメーション化可能なUIViewのプロパティ
プロパティ
可能な変更
frame
スーパービューの座標系を基準にビューのサイズと位置を変更する場合
は、このプロパティを変更します(transformプロパティに恒等変換が
含まれていない場合は、代わりにboundsまたはcenterプロパティを変
更します)。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
60
アニメーション
アニメーション化の対象
プロパティ
可能な変更
bounds
ビューのサイズを変更する場合は、このプロパティを変更します。
center
スーパービューの座標系を基準にビューの位置を変更する場合は、この
プロパティを変更します
transform
中心点を基準にビューを拡大縮小、回転、または平行移動する場合は、
このプロパティを変更します。このプロパティを使用する変換は、常に
2D空間で実行されます(3D変換を実行するには、Core Animationを使用
してビューのレイヤオブジェクトをアニメーション化する必要がありま
す)。
alpha
ビューの透明度を徐々に変更する場合は、このプロパティを変更しま
す。
backgroundColor
ビューの背景色を変更する場合は、このプロパティを変更します。
contentStretch
利用可能な空間一杯にビューのコンテンツを引き延ばす方法を変更する
場合は、このプロパティを変更します。
アニメーション化されたビューのトランジションは、ビューコントローラで提供されている以外の方
法でビュー階層を変更する方法です。ビューコントローラを使用して簡潔なビュー階層を管理するべ
きですが、ビュー階層のすべてまたは一部を置き換える必要が生じる場合もあります。このような場
合は、ビューベースのトランジションを使用して、ビューの追加や削除をアニメーション化できま
す。
より複雑なアニメーションが必要な場合、またはUIViewクラスでサポートされていないアニメーショ
ンが必要な場合は、Core Animationとビューの下位レベルのレイヤを使用してアニメーションを作成
できます。ビューおよびレイヤオブジェクトは複雑にリンクされているため、ビューのレイヤに行っ
た変更はビュー自身にも影響します。Core Animationを使用すると、ビューのレイヤに対する以下の
変更をアニメーション化できます。
●
レイヤのサイズと位置
●
変換を実行する際の中心点
●
レイヤまたはサブレイヤに対する3D空間での変換
●
レイヤ階層に対するレイヤの追加または削除
●
ほかの兄弟レイヤに対するレイヤのZ方向の順序
●
レイヤの影
●
レイヤの枠(レイヤの角を丸めるかどうかを含む)
●
サイズ変更操作中に引き延ばされるレイヤの部分
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
61
アニメーション
ビューのプロパティに対する変更のアニメーション化
●
レイヤの不透明度
●
レイヤの境界より外側にあるサブレイヤを切り取る動作
●
レイヤの現在のコンテンツ
●
レイヤのラスタライズの動作
注意: ビューがカスタムレイヤオブジェクト(関連付けられたビューを持たないレイヤオブ
ジェクト)をホストする場合は、Core Animationを使用してレイヤオブジェクトに対する変
更をアニメーション化する必要があります。
この章ではCore Animationの動作について少し触れていますが、ビューコードからの開始に関する説
明しかありません。Core Animationを使用してレイヤをアニメーション化する方法については、『Core
Animation Programming Guide 』および『Core Animation Cookbook 』を参照してください。
ビューのプロパティに対する変更のアニメーション化
UIViewクラスのプロパティに対する変更をアニメーション化するには、これらの変更をアニメーショ
ンブロック内で行う必要があります。アニメーションブロックという用語は、一般的な意味でアニ
メーション化可能な変更を指定するコードを表しています。iOS 4以降では、ブロックオブジェクトを
使用してアニメーションブロックを作成します。iOSの初期のバージョンでは、UIViewクラスの特殊
なクラスメソッドを使用して、アニメーションブロックの開始位置と終了位置を指定します。どちら
の手法も同じ設定オプションをサポートし、アニメーションの実行について制御できる内容は同じで
す。ただし、可能な場合は常にブロックベースのメソッドを使用してください。
以降のセクションでは、ビューのプロパティに対する変更をアニメーション化するために必要なコー
ドについて説明します。ビューセット間にアニメーション化されたトランジションを作成する方法に
ついては、“ビュー間のアニメーション化されたトランジションの作成” (71 ページ)を参照してく
ださい。
ブロックベースのメソッドを使用したアニメーションの開始
iOS 4以降では、ブロックベースのクラスメソッドを使用して、アニメーションを開始します。いくつ
かのブロックベースのメソッドが用意されており、それぞれ設定レベルの異なるアニメーションブ
ロックを提供します。これらのメソッドは以下のとおりです。
●
animateWithDuration:animations:
●
animateWithDuration:animations:completion:
●
animateWithDuration:delay:options:animations:completion:
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
62
アニメーション
ビューのプロパティに対する変更のアニメーション化
これらはクラスメソッドであるため、これらのメソッドを使用して作成するアニメーションブロック
は1つのビューだけに関連付けられません。したがって、これらのメソッドを使用して、複数のビュー
に対して変更を行う1つのアニメーションを作成できます。たとえば、リスト 4-1は、ビューのフェー
ドインと別のビューのフェードアウトを1秒間で実行するために必要なコードを示しています。この
コードを実行すると、現在のスレッドまたはアプリケーションのメインスレッドをブロックしないよ
うに、指定したアニメーションが別のスレッドでただちに開始されます。
リスト 4-1
簡単なブロックベースのアニメーションの実行
[UIView animateWithDuration:1.0 animations:^{
firstView.alpha = 0.0;
secondView.alpha = 1.0;
}];
上の例のアニメーションは、イーズインイーズアウトのアニメーション曲線を使用して、1度だけ実
行されます。デフォルトのアニメーションパラメータを変更する場合は、
animateWithDuration:delay:options:animations:completion:メソッドを使用してアニメーショ
ンを実行する必要があります。このメソッドでは、以下のアニメーションパラメータをカスタマイズ
できます。
●
アニメーションを開始するまでの遅延
●
アニメーション中に使用するタイミング曲線の種類
●
アニメーションを繰り返す回数
●
アニメーションを最後まで再生した後、自動的に逆再生するかどうか
●
アニメーションの再生中にタッチイベントをビューに送信するかどうか
●
アニメーションを開始するときに、再生中のアニメーションを中断して開始するか、または再生
中のアニメーションが完了するまで待機するか
また、animateWithDuration:animations:completion:と
animateWithDuration:delay:options:animations:completion:メソッドはどちらも、完了ハン
ドラブロックを指定する機能をサポートします。完了ハンドラを使用すると、アプリケーションに特
定のアニメーションが完了したことを通知できます。完了ハンドラは、別々のアニメーションをリン
クする方法としても利用できます。
リスト 4-2に、完了ハンドラを使用して、1つ目のアニメーションが完了した後に新しいアニメーショ
ンを開始するアニメーションブロックの例を示します。最初の
animateWithDuration:delay:options:animations:completion:の呼び出しで、フェードアウト
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
63
アニメーション
ビューのプロパティに対する変更のアニメーション化
のアニメーションを設定し、いくつかのカスタムオプションを設定します。このアニメーションが完
了すると、完了ハンドラは2番目のアニメーションを実行および設定します。この例では、1秒後に
ビューをもう一度フェードインしています。
完了ハンドラの使用は、複数のアニメーションをリンクする際に用いられる主な方法です。
リスト 4-2
カスタムオプションを使用したアニメーションブロックの作成
- (IBAction)showHideView:(id)sender
{
// Fade out the view right away
[UIView animateWithDuration:1.0
delay: 0.0
options: UIViewAnimationOptionCurveEaseIn
animations:^{
thirdView.alpha = 0.0;
}
completion:^(BOOL finished){
// Wait one second and then fade in the view
[UIView animateWithDuration:1.0
delay: 1.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
thirdView.alpha = 1.0;
}
completion:nil];
}];
}
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
64
アニメーション
ビューのプロパティに対する変更のアニメーション化
Important: すでに実行中のアニメーションに関連するプロパティの値を変更しても、現在のアニ
メーションは停止しません。現在のアニメーションは続行され、プロパティに割り当てた新しい
値までアニメーション化されます。
begin/commitメソッドを使用したアニメーションの開始
アプリケーションをiOS 3.2以前で実行する場合は、UIViewのクラスメソッドである
beginAnimations:context:およびcommitAnimationsを使用して、アニメーションブロックを定義
する必要があります。これらのメソッドは、アニメーションブロックの開始位置と終了位置を指定し
ます。これらのメソッド間で変更したアニメーション化可能なプロパティは、commitAnimationsメ
ソッドを呼び出した後に、新しい値までアニメーション化されます。アニメーションの実行は、現在
のスレッドまたはアプリケーションのメインスレッドをブロックしないように、別のスレッドで実行
されます。
注意: iOS 4以降のアプリケーションを作成している場合は、コンテンツのアニメーション
化にブロックベースのメソッドを使用する必要があります。これらのメソッドの使用方法に
ついては、“ブロックベースのメソッドを使用したアニメーションの開始” (62 ページ)を
参照してください。
リスト 4-3に、リスト 4-1 (63 ページ)と同じ動作をbegin/commitメソッドを使用して実装するため
に必要なコードを示します。リスト 4-1でのように、このコードはビューのフェードアウトと別の
ビューのフェードインを1秒間で実行します。ただしこの例では、別のメソッド呼び出しを使用して
アニメーションの再生時間を設定する必要があります。
リスト 4-3
簡単なbegin/commitアニメーションの実行
[UIView beginAnimations:@"ToggleViews" context:nil];
[UIView setAnimationDuration:1.0];
// Make the animatable changes.
firstView.alpha = 0.0;
secondView.alpha = 1.0;
// Commit the changes and perform the animation.
[UIView commitAnimations];
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
65
アニメーション
ビューのプロパティに対する変更のアニメーション化
デフォルトでは、アニメーションブロック内で行われたアニメーション化可能なプロパティの変更
は、すべてアニメーション化されます。一部の変更だけをアニメーション化する場合は、
setAnimationsEnabled:メソッドを使用してアニメーションを一時的に無効にし、アニメーション
化しない変更を行った後、もう一度setAnimationsEnabled:を呼び出してアニメーションを再有効
化します。アニメーションが現在有効かどうかは、areAnimationsEnabledクラスメソッドを呼び出
すことで確認できます。
注意: 実行中のアニメーションに関連するプロパティの値を変更しても、現在のアニメー
ションは停止しません。アニメーションは続行され、プロパティに割り当てた新しい値まで
アニメーション化されます。
begin/commitアニメーションのパラメータの設定
begin/commitアニメーションブロックのアニメーションパラメータを設定するには、UIViewのクラス
メソッドを使用します。表 4-2に、これらのメソッドのリストと、各メソッドを使用してアニメーショ
ンを設定する方法を示します。これらのメソッドの多くはbegin/commitアニメーションブロック内の
みから呼び出しますが、一部のメソッドはブロックベースのアニメーションでも使用できます。アニ
メーションブロックでこれらのメソッドを呼び出さなかった場合は、対応する属性のデフォルト値が
使用されます。各メソッドに関連付けられたデフォルト値については、『UIView Class Reference 』を
参照してください。
表 4-2
アニメーションブロックを設定するメソッド
メソッド
用途
setAnimationStartDate:
setAnimationDelay:
アニメーションの実行をいつ開始するかを指定する場合は、これ
らのメソッドのいずれかを使用します。指定した開始日が過去の
日付(または、遅延が0)である場合、アニメーションは可能な
限りすぐに開始されます。
setAnimationDuration:
アニメーションの実行を継続する時間を設定します。
setAnimationCurve:
アニメーションのタイミング曲線を設定します。アニメーション
を線形に実行するか、一定時間で速度を変更するかを制御しま
す。
setAnimationRepeatCount:
アニメーションを繰り返す回数と、各サイクルの終わりにアニ
メーションを逆向きに実行するかどうかを設定します。これらの
メソッドの使用方法については、“逆再生を行うアニメーション
の実装” (70 ページ)を参照してください。
setAnimationRepeatAutoreverses:
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
66
アニメーション
ビューのプロパティに対する変更のアニメーション化
メソッド
用途
setAnimationDelegate:
アニメーションの直前または直後にコードを実行する場合は、こ
れらのメソッドを使用します。デリゲートの使用方法について
は、“アニメーションデリゲートの設定” (68 ページ)を参照し
てください。
setAnimationWillStartSelector:
setAnimationDidStopSelector:
すべてのアニメーションをただちに停止して、新しいアニメー
ションを停止した位置から開始します。このメソッドに、YESの
代わりにNOを渡すと、新しいアニメーションは前のアニメーショ
ンが停止してから開始されます。
setAnimationBeginsFromCurrentState:
リスト 4-4に、リスト 4-2 (64 ページ)のコードと同じ動作をbegin/commitメソッドを使用して実装
するために必要なコードを示します。前の例と同様に、このコードはビューをフェードアウトし、1
秒待機してから再度フェードインします。アニメーションの後半部分を実装するために、コードはア
ニメーションデリゲートを設定し、停止時に呼び出されるメソッドを実装します。続いて、このハン
ドラメソッドがアニメーションの後半を設定して実行します。
リスト 4-4
begin/commitメソッドを使用したアニメーションパラメータの設定
// This method begins the first animation.
- (IBAction)showHideView:(id)sender
{
[UIView beginAnimations:@"ShowHideView" context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[UIView setAnimationDuration:1.0];
[UIView setAnimationDelegate:self];
[UIView
setAnimationDidStopSelector:@selector(showHideDidStop:finished:context:)];
// Make the animatable changes.
thirdView.alpha = 0.0;
// Commit the changes and perform the animation.
[UIView commitAnimations];
}
// Called at the end of the preceding animation.
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
67
アニメーション
ビューのプロパティに対する変更のアニメーション化
- (void)showHideDidStop:(NSString *)animationID finished:(NSNumber *)finished
context:(void *)context
{
[UIView beginAnimations:@"ShowHideView2" context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationDuration:1.0];
[UIView setAnimationDelay:1.0];
thirdView.alpha = 1.0;
[UIView commitAnimations];
}
アニメーションデリゲートの設定
アニメーションの直前または直後にコードを実行する場合は、デリゲートオブジェクトと開始または
停止セレクタを、begin/commitアニメーションブロックに関連付ける必要があります。デリゲートオ
ブジェクトはUIViewのクラスメソッドであるsetAnimationDelegate:を使用して設定し、開始セレ
クタと停止セレクタはsetAnimationWillStartSelector:およびsetAnimationDidStopSelector:
クラスメソッドを使用して設定します。アニメーションの実行中に、アニメーションシステムがデリ
ゲートメソッドを適切なタイミングで呼び出し、必要なコードを実行することができます。
アニメーションデリゲートメソッドには、以下のような署名が必要です。
- (void)animationWillStart:(NSString *)animationID context:(void *)context;
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished
context:(void *)context;
各メソッドのanimationIDおよびcontextパラメータは、アニメーションブロックの先頭で
beginAnimations:context:メソッドに渡す同じパラメータです。
●
animationID - アニメーションを識別するための、アプリケーションが提供する文字列です。
●
context - デリゲートに追加情報を渡すために使用できる、アプリケーションが提供するオブジェ
クトです。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
68
アニメーション
ビューのプロパティに対する変更のアニメーション化
setAnimationDidStopSelector:セレクタメソッドには、Booleanのパラメータがもう一つあります。
アニメーションが最後まで実行されると、このパラメータの値がYESになります。このパラメータの
値がNOの場合は、アニメーションがキャンセルされたか、ほかのアニメーションによって途中で停止
されています。
注意: アニメーションデリゲートはブロックベースのメソッドでも使用できますが、一般的
に、この場合は使用する必要がありません。代わりに、アニメーションの前に実行するコー
ドをブロックの先頭に置き、アニメーションが完了した後に実行するコードを完了ハンドラ
に配置します。
アニメーションブロックのネスト
別のアニメーションブロックをネストすることで、アニメーションブロックの各部分に異なるタイミ
ングや設定オプションを割り当てることができます。ネストされたアニメーションブロックは、名前
からわかるように、既存のアニメーションブロック内に作成された新しいアニメーションブロックで
す。ネストされたアニメーションは親アニメーションと同時に開始されますが、大部分は独自の設定
オプションに従って実行されます。デフォルトでは、ネストされたアニメーションは親の再生時間と
アニメーション曲線を継承しますが、これらのオプションも必要に応じてオーバーライドできます。
リスト 4-5に、ネストされたアニメーションを使用して一部のアニメーションのタイミング、再生時
間、および動作をグループ全体で変更する方法の例を示します。この例では、2つのビューが完全に
透明になるまで変化していますが、anotherViewオブジェクトの透明度は最終的に非表示なるまでに
何度か元に戻っています。ネストされたアニメーションブロックで使用されている
UIViewAnimationOptionOverrideInheritedCurveおよび
UIViewAnimationOptionOverrideInheritedDurationキーで、1つ目のアニメーションの曲線と再
生時間の値を、2つ目のアニメーションで変更することができます。これらのキーがない場合は、代
わりに親のアニメーションブロックの再生時間と曲線が使用されます。
リスト 4-5
設定の異なるアニメーションのネスト
[UIView animateWithDuration:1.0
delay: 1.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
aView.alpha = 0.0;
// Create a nested animation that has a different
// duration, timing curve, and configuration.
[UIView animateWithDuration:0.2
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
69
アニメーション
ビューのプロパティに対する変更のアニメーション化
delay:0.0
options: UIViewAnimationOptionOverrideInheritedCurve |
UIViewAnimationOptionCurveLinear |
UIViewAnimationOptionOverrideInheritedDuration |
UIViewAnimationOptionRepeat |
UIViewAnimationOptionAutoreverse
animations:^{
[UIView setAnimationRepeatCount:2.5];
anotherView.alpha = 0.0;
}
completion:nil];
}
completion:nil];
begin/commitメソッドを使用してアニメーションを作成している場合、ネストはブロックベースのメ
ソッドの場合とほぼ同様に機能します。すでに開いているアニメーションブロック内で
beginAnimations:context:を呼び出すごとに、新しいネストされたアニメーションブロックが作成
され、必要に応じて設定できます。行った変更はすべて、最後に開いたアニメーションブロックに適
用されます。すべてのアニメーションブロックは、アニメーションを送信して実行する前に、
commitAnimationsを呼び出して閉じる必要があります。
逆再生を行うアニメーションの実装
逆再生可能なアニメーションを作成するときに繰り返し回数を使用する場合は、繰り返し回数に整数
以外の値を指定することも考慮します。自動で逆再生するアニメーションの場合は、アニメーション
の1サイクルで、元の値から新しい値までアニメーションが実行された後、もう一度元の値まで戻り
ます。アニメーションを新しい値で終了する場合は、繰り返し回数に0.5を加算して、アニメーショ
ンを新しい値で終了するために必要な半分のサイクルを追加します。この半分のサイクルを追加しな
いと、アニメーションは元の値まで再生された後すぐに新しい値に変更され、必要な視覚効果が得ら
れません。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
70
アニメーション
ビュー間のアニメーション化されたトランジションの作成
ビュー間のアニメーション化されたトランジションの作成
ビューのトランジションを利用すると、ビュー階層でのビューの追加、削除、または非表示と表示の
切り替えに関して、変更が突然表示されるのを防ぐことができます。以下のような変更を実装するに
は、ビューのトランジションを使用します。
●
●
既存のビューの表示しているサブビューを変更する。既存のビューに比較的小規模な変更を行う
場合は、一般的にこの方法を選択します。
ビュー階層で、あるビューを別のビューに置き換える。画面の全体またはほとんどを占めるビュー
階層を置き換える場合は、一般的にこの方法を選択します。
Important: ビューコントローラが開始するトランジション(モーダルビューコントローラの表示
や、ナビゲーションスタックへの新しいビューコントローラのプッシュなど)と、ビューのトラ
ンジションを混同しないでください。ビューのトランジションはビュー階層にだけ影響しますが、
ビューコントローラのトランジションはアクティブなビューコントローラも変更します。したがっ
て、ビューのトランジションでは、トランジションの開始時にアクティブなビューコントローラ
はトランジションが完了したときもアクティブなままです。
ビューコントローラを使用して新しいコンテンツを表示する方法については、『View Controller
Programming Guide for iOS 』を参照してください。
ビューのサブビューの変更
ビューのサブビューを変更すると、ビューに中規模の変更を行うることができます。たとえば、サブ
ビューを追加または削除して、スーパービューの2つの状態を切り替えることができます。アニメー
ションの終了時には、同じビューが表示されていますがコンテンツは異なります。
iOS 4以降では、transitionWithView:duration:options:animations:completion:メソッドを使
用して、ビューのトランジションアニメーションを開始します。このメソッドに渡されるアニメー
ションブロックでは、通常アニメーション化される変更はサブビューの表示と非表示の切り替え、追
加、または削除に関連する変更だけです。これらの変更だけにアニメーションを限定することで、
ビューは変更の前後のスナップショットイメージを作成し、2つのイメージ間で効率よくアニメーショ
ン化を実行できます。ただし、その他の変更をアニメーション化する必要がある場合は、メソッドを
呼び出すときにUIViewAnimationOptionAllowAnimatedContentオプションを指定できます。この
オプションを指定すると、ビューによるスナップショットの作成が行われず、すべての変更が直接ア
ニメーション化されます。
リスト 4-6に、トランジションアニメーションを使用して、新しいテキストの入力ページが追加され
たように見せる例を示します。この例では、メインビューに埋め込みのテキストビューが2つ含まれ
ています。2つのテキストビューの設定はほぼ同じですが、一方は常に表示され、もう一方は常に非
表示になるように設定されています。ユーザがボタンをタップして新しいページを作成すると、この
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
71
アニメーション
ビュー間のアニメーション化されたトランジションの作成
メソッドは2つのビューの表示設定を切り替えます。結果的に、テキストを入力可能な空のテキスト
ビューを使用して、新しい空のページが表示されます。トランジションが完了すると、ビューはプラ
イベートなメソッドを使用して古いページのテキストを保存し、非表示にしたテキストビューを後で
再利用できるようにリセットします。続いて、ビューはポインタを整理し、ユーザが別の新しいペー
ジを要求したときに同じ処理を行えるように準備します。
リスト 4-6
既存のテキストビューと空のテキストビューの切り替え
- (IBAction)displayNewPage:(id)sender
{
[UIView transitionWithView:self.view
duration:1.0
options:UIViewAnimationOptionTransitionCurlUp
animations:^{
currentTextView.hidden = YES;
swapTextView.hidden = NO;
}
completion:^(BOOL finished){
// Save the old text and then swap the views.
[self saveNotes:temp];
UIView*
temp = currentTextView;
currentTextView = swapTextView;
swapTextView = temp;
}];
}
iOS 3.2以前でビューのトランジションを実行する必要がある場合は、
setAnimationTransition:forView:cache:メソッドを使用してトランジションのパラメータを指定
できます。このメソッドに渡すビューは、
transitionWithView:duration:options:animations:completion:メソッドに1つ目のパラメータ
として渡すビューと同じです。リスト 4-7に、アニメーションブロックで作成する必要がある基本的
な構造を示します。リスト 4-6 (72 ページ)に示す完了ブロックを実装するには、“アニメーション
デリゲートの設定” (68 ページ)で説明するように、停止時に呼び出されるハンドラを使用してアニ
メーションデリゲートを設定する必要があります。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
72
アニメーション
ビュー間のアニメーション化されたトランジションの作成
リスト 4-7
begin/commitメソッドを使用したサブビューの変更
[UIView beginAnimations:@"ToggleSiblings" context:nil];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.view
cache:YES];
[UIView setAnimationDuration:1.0];
// Make your changes
[UIView commitAnimations];
別のビューへの置き換え
ビューの置き換えは、インターフェイスを劇的に変化させたいときに使用できます。この方法では
ビューだけが入れ替わるため(ビューコントローラは入れ替わりません)、デベロッパはアプリケー
ションのコントローラオブジェクトを適切に設計する必要があります。この方法は、単に標準のトラ
ンジションをいくつか使用して新しいビューをすばやく表示するだけです。
iOS 4以降では、2つのビュー間でトランジションを行うには、
transitionFromView:toView:duration:options:completion:メソッドを使用します。このメソッ
ドは、実際に1つ目のビューをビュー階層から削除して、別のビューを挿入します。したがって、1つ
目のビューを維持しておきたい場合は、ビューの参照を保持する必要があります。ビュー階層から削
除する代わりにビューを非表示にする場合は、UIViewAnimationOptionShowHideTransitionViews
キーをオプションの1つとして渡します。
リスト 4-8に、1つのビューコントローラで管理される2つのメインビューを入れ替えるために必要な
コードを示します。この例では、ビューコントローラのルートビューは常に2つの子ビュー
(primaryViewまたはsecondaryView)のいずれかを表示します。各ビューは同じコンテンツを表示
しますが、表示する方法がそれぞれ異なります。ビューコントローラは、displayingPrimaryメン
バー変数(ブール値)を使用し、任意の時点でどちらのビューが表示されているかを常に追跡してい
ます。入れ替える方向は、どちらのビューが表示されているかに応じて変化します。
リスト 4-8
ビューコントローラの2つのビューの切り替え
- (IBAction)toggleMainViews:(id)sender {
[UIView transitionFromView:(displayingPrimary ? primaryView : secondaryView)
toView:(displayingPrimary ? secondaryView : primaryView)
duration:1.0
options:(displayingPrimary ? UIViewAnimationOptionTransitionFlipFromRight
:
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
73
アニメーション
複数のアニメーションのリンク
UIViewAnimationOptionTransitionFlipFromLeft)
completion:^(BOOL finished) {
if (finished) {
displayingPrimary = !displayingPrimary;
}
}];
}
注意: ビューの入れ替えに加え、ビューコントローラのコードでは、1つ目のビューと2つ
目のビューの両方のロードおよびアンロードを管理する必要があります。ビューコントロー
ラでビューをロードおよびアンロードする方法については、『View Controller Programming
Guide for iOS 』を参照してください。
複数のアニメーションのリンク
UIViewアニメーションインターフェイスでは、独立したアニメーションブロックのリンクがサポー
トされ、これらのアニメーションを同時でなく順番に実行できます。アニメーションブロックをリン
クするプロセスは、ブロックベースのアニメーションメソッドを使用しているか、begin/commitメ
ソッドを使用しているかで異なります。
●
●
ブロックベースのアニメーションでは、animateWithDuration:animations:completion:およ
びanimateWithDuration:delay:options:animations:completion:メソッドでサポートされ
る完了ハンドラを使用して、後に続くアニメーションを実行します。
begin/commitアニメーションでは、デリゲートオブジェクトと停止時のセレクタをアニメーショ
ンに関連付けます。デリゲートをアニメーションに関連付ける方法については、“アニメーション
デリゲートの設定” (68 ページ)を参照してください。
複数のアニメーションをリンクする代わりに、ネストしたアニメーションに別々の遅延を設定し、各
アニメーションを異なるタイミングで開始することもできます。アニメーションをネストする方法に
ついては、“アニメーションブロックのネスト” (69 ページ)を参照してください。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
74
アニメーション
ビューとレイヤの変更の同時アニメーション化
ビューとレイヤの変更の同時アニメーション化
アプリケーションには、必要に応じてビューベースとレイヤベースのアニメーションコードを自由に
混在させることができます。ただし、アニメーションパラメータを設定するプロセスはレイヤの所有
者によって異なります。ビューが所有するレイヤの変更は、ビュー自体を変更するのと同じです。レ
イヤのプロパティに適用するアニメーションでは、現在のビューベースのアニメーションブロックに
設定されたアニメーションパラメータが使用されます。デベロッパが作成したレイヤでは動作が異な
ります。カスタムレイヤオブジェクトはビューベースのアニメーションブロックのパラメータを無視
し、代わりにデフォルトのCore Animationパラメータを使用します。
作成するレイヤのアニメーションパラメータをカスタマイズする場合は、直接Core Animationを使用
する必要があります。一般的に、Core Animationを使用してレイヤをアニメーション化する場合は、
CABasicAnimationオブジェクトまたはCAAnimationの具象サブクラスをいくつか作成します。その
後、対応するレイヤにそのアニメーションを追加します。アニメーションはビューベースのアニメー
ションブロックの内部または外部のどちらからでも適用できます。
リスト 4-9に、ビューとカスタムレイヤを同時に変更するアニメーションを示します。この例のビュー
は、境界の中心に配置されたカスタムCALayerオブジェクトを含んでいます。アニメーションはビュー
を反時計回りに回転し、レイヤを時計回りに回転します。ビューとレイヤが逆方向に回転しているた
め、レイヤは画面に対して元の向きを保ち、ほとんど回転しているようには見えません。ただし、レ
イヤの下にあるビューは360度回転して、元の向きに戻ります。この例の主な目的は、ビューとレイ
ヤのアニメーションをどのように混在できるかを示すことです。正確なタイミングが必要な状況で
は、このタイプの混在を使用しないでください。
リスト 4-9
ビューとレイヤのアニメーションの混在
[UIView animateWithDuration:1.0
delay:0.0
options: UIViewAnimationOptionCurveLinear
animations:^{
// Animate the first half of the view rotation.
CGAffineTransform xform =
CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(-180));
backingView.transform = xform;
// Rotate the embedded CALayer in the opposite direction.
CABasicAnimation*
layerAnimation = [CABasicAnimation
animationWithKeyPath:@"transform"];
layerAnimation.duration = 2.0;
layerAnimation.beginTime = 0; //CACurrentMediaTime() + 1;
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
75
アニメーション
ビューとレイヤの変更の同時アニメーション化
layerAnimation.valueFunction = [CAValueFunction
functionWithName:kCAValueFunctionRotateZ];
layerAnimation.timingFunction = [CAMediaTimingFunction
functionWithName:kCAMediaTimingFunctionLinear];
layerAnimation.fromValue = [NSNumber numberWithFloat:0.0];
layerAnimation.toValue = [NSNumber
numberWithFloat:DEGREES_TO_RADIANS(360.0)];
layerAnimation.byValue = [NSNumber
numberWithFloat:DEGREES_TO_RADIANS(180.0)];
[manLayer addAnimation:layerAnimation forKey:@"layerAnimation"];
}
completion:^(BOOL finished){
// Now do the second half of the view rotation.
[UIView animateWithDuration:1.0
delay: 0.0
options: UIViewAnimationOptionCurveLinear
animations:^{
CGAffineTransform xform =
CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(-359));
backingView.transform = xform;
}
completion:^(BOOL finished){
backingView.transform = CGAffineTransformIdentity;
}];
}];
注意: リスト 4-9 (75 ページ)で、CABasicAnimationオブジェクトをビューベースのア
ニメーションブロックの外部で作成および適用しても、同じ結果を得ることができます。す
べてのアニメーションの実行は最終的にCore Animationに依存するため、ほぼ同時に送信さ
れていれば、アニメーションは一緒に実行されます。
ビューベースのアニメーションとレイヤベースのアニメーションとの間に正確なタイミングが必要な
場合は、すべてのアニメーションをCore Animationを使用して作成することをお勧めします。いくつ
かのアニメーションはCore Animationを使用した方が簡単に実行できます。たとえば、リスト
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
76
アニメーション
ビューとレイヤの変更の同時アニメーション化
4-9 (75 ページ)におけるビューベースの回転では、180度を超える回転を行うために複数のステッ
プを必要としていますが、Core Animation部分では回転の評価関数を使用し、開始値から終了値まで
の回転を中間値を経由して実行しています。
Core Animationを使用してアニメーションを作成および設定する方法については、『Core Animation
Programming Guide 』および『Core Animation Cookbook 』を参照してください。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
77
書類の改訂履歴
この表は「iOS Viewプログラミングガイド 」の改訂履歴です。
日付
メモ
2014-09-17
TBD
2013-10-22
OpenGL ESを使って描画するビューに関するアドバイスを改訂しま
した。
2011-03-08
文書の内容を再編し、拡充しました。
ビューベースのアニメーションを作成する方法についての情報を追
加しました。
コンテンツを外部ディスプレイに表示する方法についての情報を追
加しました。
高解像度画面を操作する方法についての情報を追加しました。
2010-05-17
ビュー、ウインドウ、およびその他のビジュアルインターフェイス
要素の作成と管理について説明した新規文書。
2014-09-17 | Copyright © 2014 Apple Inc. All Rights Reserved.
78
Apple Inc.
Copyright © 2014 Apple Inc.
All rights reserved.
本書の一部あるいは全部を Apple Inc. から書
面による事前の許諾を得ることなく複写複製
(コピー)することを禁じます。また、製品
に付属のソフトウェアは同梱のソフトウェア
使用許諾契約書に記載の条件のもとでお使い
ください。書類を個人で使用する場合に限り
1 台のコンピュータに保管すること、またそ
の書類にアップルの著作権表示が含まれる限
り、個人的な利用を目的に書類を複製するこ
とを認めます。
Apple ロゴは、米国その他の国で登録された
Apple Inc. の商標です。
キーボードから入力可能な Apple ロゴについ
ても、これを Apple Inc. からの書面による事
前の許諾なしに商業的な目的で使用すると、
連邦および州の商標法および不正競争防止法
違反となる場合があります。
本書に記載されているテクノロジーに関して
は、明示または黙示を問わず、使用を許諾し
ません。 本書に記載されているテクノロジー
に関するすべての知的財産権は、Apple Inc.
が保有しています。 本書は、Apple ブランド
のコンピュータ用のアプリケーション開発に
使用を限定します。
本書には正確な情報を記載するように努めま
した。 ただし、誤植や制作上の誤記がないこ
とを保証するものではありません。
Apple Inc.
1 Infinite Loop
Cupertino, CA 95014
U.S.A.
Apple Japan
〒106-6140 東京都港区六本木
6丁目10番1号 六本木ヒルズ
http://www.apple.com/jp
Offline copy. Trademarks go here.
Apple Inc. は本書の内容を確認しておりますが、本
書に関して、明示的であるか黙示的であるかを問わ
ず、その品質、正確さ、市場性、または特定の目的
に対する適合性に関して何らかの保証または表明を
行うものではありません。その結果、本書は「現状
有姿のまま」提供され、本書の品質または正確さに
関連して発生するすべての損害は、購入者であるお
客様が負うものとします。
いかなる場合も、Apple Inc. は、本書の内容に含ま
れる瑕疵または不正確さによって生じる直接的、間
接的、特殊的、偶発的、または結果的損害に対する
賠償請求には一切応じません。そのような損害の可
能性があらかじめ指摘されている場合においても同
様です。
上記の損害に対する保証および救済は、口頭や書面
によるか、または明示的や黙示的であるかを問わ
ず、唯一のものであり、その他一切の保証にかわる
ものです。 Apple Inc. の販売店、代理店、または従
業員には、この保証に関する規定に何らかの変更、
拡張、または追加を加える権限は与えられていませ
ん。
一部の国や地域では、黙示あるいは偶発的または結
果的損害に対する賠償の免責または制限が認められ
ていないため、上記の制限や免責がお客様に適用さ
れない場合があります。 この保証はお客様に特定
の法的権利を与え、地域によってはその他の権利が
お客様に与えられる場合もあります。