CS193p 課題3の内容

CS193pのクラスの公式サイトにLecture 6の課題としてAssignment3.pdfがアップされています。その課題の内容を以下に日本語にしておきます。ヒントの中には講義の補足のようなものもあるので読むことで新しい知識を得ることが出来ます。

Required Taskの#8は、次のLecture 7で詳しい講義があります。

 

課題の内容

ゴール

電卓アプリのコードを再利用してiPhoneとiPadで動作するグラフ電卓を作成する。

事前準備

前回の課題を今回の課題に使うことが出来る。使う前に、元の課題は別にコピーして取っておこう。

 

Required Task

1. iPhoneでは、課題2の電卓UIがUINavigationControllerの中で動作するようにする


2. ボタンの削除

変数のボタンはxだけにしてその他の変数ボタンや変数のテスト用のボタンは削除する。

 

3. グラフボタンを電卓のUIに追加

グラフボタンが押されたら、iPhone上のUINavigationControllerのスタックにプッシュして新しいMVCに遷移させる。
新しいMVCグラフはボタンが押された時に演算スタックの内容をグラフにする。グラフの描画は、xと+runProgram:usingVariableValues:を使って得られたyの値を使ってViewの中にピクセルを繰り返しプロットすることで行う。
この座標系の変換にscaleとoriginが必要になるだろう。
ユーザーがscaleとoriginを指定していない場合は、手頃な値を最初に使う。

 

4. グラフ描画時は、演算スタックの内容を表示させる

グラフが画面に表示されている時は常に演算スタックの内容

(例えば+descriptionOfProgram:メソッドの戻り値)をどこかに表示させるべきである。これは、iPhoneとiPadでは違う場所になるかもしれない。

 

5. 座標軸の描画は、提供されたコードを使う

新しいMVCを実装するためには、演算スタックをプロットするのに加えて、グラフの座標軸を表示するようにカスタムViewを記述しないといけない。そのコードは、クラスのwebサイトにあって、与えられたoriginのポイントとscaleを使って軸を描くようになっているので、座標軸をCore Graphicsのコードで記述する必要はない。演算スタックの内容をグラフ描画するだけでよい。

この座標軸の描画を調べれば縮尺の動作方法が理解出来るので、この課題や以下の課題をやる前に見てみると良い。

 

6. 作成するグラフのUIViewは一般的で再利用可能にする

例えば、このViewは、一般的なx-yグラフのクラスであるべきで、CalculatorBrainについては何も知らない。
Viewはデータを持たないので、データを取得するのにプロトコルを使うこと。

 

7. グラフのViewでジェスチャをサポートする

・ピンチ(Viewのscaleを調整)
・パン(軸を含めてグラフ全体を移動させ、動き回すようなタッチにも従う)
・トリプルタップ(originをタップしたポイントに移動させる)

 

8. iPadでも動作させる

2つのstoryboadを使って電卓アプリをiPadでも動作させる。(ユニバーサルアプリのような単一のアプリで実現する)1つはiPhone用でもう1つはiPad用にし、iPadのほうはUISplitViewControllerを使って画面の左側に(もしくはポップオーバーで)前回の課題の電卓MVCを表現し、右側には新しいグラフMVCを表現する。

2つのMVCを同時に画面に表示させるので、segueは必要ない。その代わり、UISplitViewControllerのAPIを使って他のMVCのポインタを取得する必要がある。グラフボタンが押された時は画面の右側だけを更新すべきである。

 

9. 回転時のことも考慮すること

全てのデバイスで回転をサポートする必要はないが、サポートするデバイスではユーザインタフェイスは全てのケースでよく見えるようにすべきである。(そこで、storyboardのstruts and springを正確に設定する)

 

10. scaleとoriginを保存する

一旦ユーザがピンチしてscaleが決まるか、ピンチかタップで新しいoriginが決まったら、そのscaleとoriginを新しい演算やアプリを再起動した時に使えるように、新しい値はNSUserDefaultsに格納すべきである。

 

ヒント

1. 新しいMVCを作る前に最初の2つの課題を動作させよう

 

2.コードファイルの再利用

プロジェクトにファイルをドラッグする時は、"Copy items into destination group's folder (if needed)"のチェックボックスをチェック状態にすること。

 

3. 新規ファイルの追加

新規のMVCやiPad用のstoryboardを作る時は、Xcodeのメニューで"New File…"から行う。

 

4. 新UIViewControllerと新UIVewは、この課題で一から記述する唯一の新規クラスである

 

5. グラフ描画用の新コントローラは、他のMVCのコントローラに似ている

それはモデル(何がモデルになると思う?)とViewへのアウトレットが必要になるだろう。この課題に取りかかる前に、コントローラにモデルの@propertyを追加しよう。このモデルとCalculatorViewControllerのモデルと混同しないように。これらは別のものである。そして、考えすぎないように。

 

6. 新View Controllerの設定

新しいUIViewControllerを作る際、オブジェクトライブラリからstoryboardにドラッグした後、Identity Inspectorで設定するのを忘れないように。

 

7. 最初にsegueを設定する

簡単にテスト出来るようにするために、全てのMVCをstoryboardで接続した後に、グラフ描画用のUIViewでdrawRect:を実装するのはいいやり方かもしれない。

 

8.新コントローラと新ビューの実装内容

グラフ描画用のビューへのポインタとして新しいコントローラの中にIBOutletが必要になるだろう。グラフ描画用のビューはデータソースがdelegateされてセットされ、ジェスチャ認識が追加される必要があるだろう。そして、データソースのdelegateのデータが違う値に更新された時にはそれとやりとりして自分自身で再描画する必要があるだろう。

 

9.ユニバーサルアプリへの変更方法

CalculatorのターゲットのSammaryタブの中で、既存のiPhone用のプロジェクトからユニバーサルなプロジェクトにコンバートすることができる。(ナビゲータの一番上にあるアイコンをクリックして、それからターゲットの下にあるCalculatorをクリック)これは自分がセットしているstoryboardがどのプラットフォームで使われているかも示している。

 

10.Split View Controllerの設置

Split View Controllerをオブジェクトライブラリからstoryboardにドラッグしたら、デフォルトでsplitビューコントローラの左側にテーブルビューを持ったナビゲーションコントローラが追加される。それは必要ないので、そのコントローラを削除して新しいUIViewControllerをオブジェクトライブラリからドラッグして(CalculatorViewControllerのクラスとして設定し)、ctrl-dragでsplitビューのマスターとして接続する。

 

11.iPad用のストーリーボードが動かない原因

iPadバージョンを作成する際、CalculatorのUIをストーリーボードから他のストーリーボードへコピー&ペーストすることになるだろう。そしてボタンとラベルをまたひも付けなければならないかもしれない(ストーリーボード間でビューのコピー&ペーストはターゲットとアクションやアウトレットの接続は保持されないが、コントローラのコピー&ペーストはそれが行われる)iPadのストーリーボードが上手く動作しない一番の原因は、アウトレットをひもづけるのを忘れている。(例えば、グラフビューやディスプレイへのアウトレットや、ボタンからターゲット/アクションへの接続である)

 

12. グラフ描画用のdrawRect: の実装方法

drawRect: の実装を行う際、まず最初に座標軸を描画するヘルパーメソッドが必要になるだろう。(ヒント2に気をつけてプロジェクトにドラッグ)簡単に自分で実装するために、ヘルパークラスがやっているのと同じやり方で縮尺を決めるのがいい。(クラスのヘッダファイルの中に記述されている)このヘルパークラスを使うためには、色などのグラフの状態を設定して、drawRect:の中でそのクラスのメソッドを呼び出す。それは自動的に現在保持してるコンテキストを使うようになっている。

 

13. グラフ描画用のdrawRect: での描画方法

カスタムdrawRect:の実装は、見かけによらずシンプルである。ビューの中の描画したい領域で横幅分ピクセルを繰り返して、カスタムUIViewの座標系からグラフを描画している座標系に水平位置を変換するだけである。(これはx軸になる)そして、データソースdelegateにそのxに対応するy軸の位置を尋ねて、UIViewの座標系に変換すればよい。そしてCore Graphicsを使って次のポイントを描画する。

 

14. scaleとorigin

グラフのUIViewのscaleとoriginはデータではない。それらはデータをどのように描画するかを制御するUIViewのプロパティである。だからそれらはdelegateされる必要はない。特定の状況では、ビューにもっと複雑な描画用のプロパティを(さらにいくつかのデータソースを加えて)delegateすることは有益であるかもしれないが、ここでは必要ない。

 

15. グラフのプロットの方法

グラフを描画するのにポイントからポイントへ線を引くのは良いやり方ではない。(特にズームアウトされて引き離れてしまったり、継続値がない場合に)しかし、この課題では、その実装が簡単なのと厳密に行うには多くの時間がかかるのでそれをやってもよい。この課題の最後に記述されているExtra Creditをチェックすること。

 

16. プロットはピクセル単位で行う

iPhone4のRetinaディスプレイの高解像度の恩恵を受けるために、x軸の変化はポイントではなくピクセルで繰り返し処理を行うこと。UIViewのcontentScaleFactorを覚えてください。

 

17. 描画用属性のセッターを実装

誰かがグラフ描画用の属性を変更した時に再描画が必要ということをビューにマークするためにその属性のセッターを実装したくなるだろう。

 

18. contentModeの設定値

実装するdrawRect: がとても高解像度なので、グラフのビューのcontentModeはほぼ確実にUIViewContentModeRedrawになるだろう。

 

19.ジェスチャのハンドリング

ズームイン・アウトは、単にビューの座標系とグラフの座標系の間のscaleの変換を行うだけである。言い換えれば、ピンチのジェスチャハンドラーは、とてもシンプルであるべきだ。同様に、パンとタップもoriginについての変換するだけである。

 

20. デバイス回転時の位置

デバイスを回転させた時に、グラフのoriginがビューの左上からの相対位置にあるのはいい。(対して、ビューの中心からの相対位置にあるのは、例えばそれはユーザがもっと期待していることかもしれない)

 

21. 実装方法が上手くいっているかどうかの確認

これら全てのことがPsychologistとHappinessのデモととても似ていることに気が付けば、それは正しく出来ているということである。

 

22. コードのステップ数

ガイドとして、この全ての課題が100ステップ以内のコードで出来る。CalculatorViewControllerに一握りのコードが付け加えられるだけで、CalculatorBrainは全く変更する必要がない。

 

23. 動作確認

アプリをテストするために、演算スタックにsin(x)を入力するか、mx+bという簡単な一次方程式を入力するか、2次方程式を入力してみる。xを使わずににやってみる。1/xやcon(1/x)などの不連続値の関数でやってみる。基本的には、自分がおかしくなりそうだと思うことを試してみる。

 

24. 課題で考えるべきこと

この課題の考えるべき事柄は、再利用性とscaleとoriginを保持するNSUserDefaultsのキーのスコープである。ビュー単位、コントローラ単位、アプリケーション単位、もしくはその他の単位のどの単位で保存しようとしてる?例えば、将来のバージョンで2つのグラフビューを画面上に同時に表示することになったらどうなる?それらのscaleとoriginはお互いに関連して欲しくないだろう。これには正解はないので、自分なりの最良のやり方でやること。

 

25.iPadのsplitビューのdelegate

ほぼ確実にiPadではグラフのビューコントローラがsplitビューのdelegateになるだろう。というのも、Calculatorのビューが回転で隠れた時、それがツールバーの中にボタンを出さないといけないからだ。これはPsychologistがそうしたよりももっとシンプルである。

 

<前の記事 

CS193p LEcture 6  - グラフ電卓の出来上がり具合 次の記事>