Fork me on GitHub

Views

プロジェクトを実行することができたので、画面上にものを配置してみましょう。

アプリケーションで表示されている「もの」は「ビュー」と呼ばれます。1 つのビューはたくさんの「サブビュー」を持つことができます。ビューを移動するときには、そのサブビューも移動します。サブビューは、親のビュー上で階層状に積み重ねられます。

コードでは、これらは UIView オブジェクトになります。画面上で目にするすべてのものは UIView の子孫です。それらは便利な機能をたくさん持っていますが、今すぐに気にすべきなものは次の機能です。

  1. frame プロパティは、 ビューの xy 座標、ビューの大きさである widthheight という値からなります。
  2. subviews プロパティは、ビューのすべてのサブビューからなる配列で、背後から前面という視覚的な並びになっています (subviews の配列からビューを取り出すときに指定する index 値は、そのビューの "z-order" のような感じです)。

frame は、ビューの形や親のビューとの相対的な位置を表します。説明が多いので、簡単な例を示します。座標 (10, 10) にビューがあるのを想像してください。そのビューの新しいサブビューとして、画面上の座標 (50, 50) に表示されるビューが欲しいです。そのため、新しいビューの frame に座標 (40, 40) を設定する必要があります。わかりました?

アプリケーションの基本となるビューは "window" です。ほかのすべてのビューは window のサブビューか、またはそのサブビュー (またそのサブビュー、そのまた・・・) です。 アプリケーションの window は UIWindow と呼ばれる UIView のサブクラスです。

さぁ、コードを書いてみましょう。AppDelegatedidFinishLaunching メソッドを次のように変更します。

def application(application, didFinishLaunchingWithOptions:launchOptions)
  # UIScreen describes the display our app is running on
  @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
  @window.makeKeyAndVisible

  @blue_view = UIView.alloc.initWithFrame(CGRectMake(10, 10, 100, 100))
  @blue_view.backgroundColor = UIColor.blueColor
  @window.addSubview(@blue_view)

  true
end

このコードをたどってみましょう。画面の大きさの UIWindow インスタンスを作成し、makeKeyAndVisible を呼び出しています。これは、基本的にこの window は 1 つのタッチイベントを受信し画面上に表示される必要があることを OS に指示しています。(もし興味があれば複数の画面に複数の window を表示することができますが、ここでは小さな第一歩を刻みましょう)。

window を作成し、それから、window のサブビューとして新しいビューを作成します。ビューの frame には、実際には CGRectMake(x, y, w, h) を使用して作成した CGRect オブジェクトが格納されています。気をつけてください!CGRect は実際には 2 つのオブジェクト CGPointCGSize で構成されます。座標 y を参照したい場合には view.frame.position.y、高さを参照したい場合には view.frame.size.height となります。

また、色で遊ぶ方法について UIColor が示されています。UIColor はいくつか明確なデフォルト値 (blueColor, redColor など) がありますが、任意の配色を作成するために使用することができます。

FULL DISCLOSURE: UIWindowUIView を単独で直接追加することは一般的に良い考えではありませんが、勉強するためには良いことです。そのため、製品のコードではそれを行いません。

アプリケーションを実行すると (rake を実行します。覚えてる?)、青いボックスが見て取れます。

blue box

もっとボックスを追加して、よりエキサイティングにしましょう!

  ...
  @blue_view = UIView.alloc.initWithFrame(CGRectMake(10, 10, 100, 100))
  @blue_view.backgroundColor = UIColor.blueColor
  @window.addSubview(@blue_view)

  @green_view = UIView.alloc.initWithFrame(CGRectMake(30, 30, 40, 40))
  @green_view.backgroundColor = UIColor.greenColor
  @window.addSubview(@green_view)

  @red_view  = UIView.alloc.initWithFrame(CGRectMake(30, 30, 40, 40))
  @red_view.backgroundColor = UIColor.redColor
  # NOTE: *not* adding to @window
  @blue_view.addSubview(@red_view)
  ...

再び rake を実行します。赤いビューが緑のビューよりも下側にあることがわかります。一見、同じ frame にもかかわらず?

more boxes

おもしろいので、インタラクティブな REPL で遊んでみましょう。rake を実行した Terminal は、シミュレータを開いている間、irb のようなプロンプトが表示されます。さぁ、@blue_view を見つけてみましょう。

> delegate = UIApplication.sharedApplication.delegate
=> #<AppDelegate>
> blue_view = delegate.instance_variable_get('@blue_view')
=> #<UIView>

私たちは何をしたのでしょうか? UIApplication.sharedApplication は、システムがアプリケーションを描画するために使用するオブジェクトを返してくれます。delegate を使用するための設定について以前述べましたが、 .delegate で返されるものはそのオブジェクトです。そのオブジェクトを手に入れれば、ビューを取得するために、便利な instance_variable_get を使うことができます。

ビューがサブビューを 1 つ持っていることを blue_view.subviews.count で確認することができます。red_view を取得して、そのビューを削除してみましょう。

> blue_view.subviews.count
=> 1
> red_view = blue_view.subviews[0]
=> #<UIView>
> red_view.removeFromSuperview
=> #<UIView>

ビューは消えました。removeFromSuperview メソッドは、自身のビューを画面から削除します。そして、red_view は親のビューの subviews でした (再び blue_view.subviews.count を実行することで確認できます)。

Wrap Up

この例はそれほど長くはありませんでしたが、ビューの核となるコンセプト、ビューには frame とサブビューがあることを説明しました。例ではシンプルでしたが、実際にアプリケーションを作成するとはるかに複雑になります。したがって、私たちはそれらを対処するためにより良い基盤が必要です。

まとめ

  • 画面上のすべてのものは UIView です。
  • アプリケーションの基本となるビューは UIWindow のインスタンスです。ほかのビューは UIWindow の子孫です。 UIWindow を delegate で作成します。
  • ビューはサブビューを持っていて、UIView#addSubview で追加します。サブビューはお互いの上に積み重ねられます。

次の章にムーンウォークしよう!あなたの手はコントローラで汚れるよ!


Like it? Spread the word