LoginSignup

This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

More than 5 years have passed since last update.

[個人メモ]iOSプログラミングにおける概念のまとめ

Last updated at Posted at 2014-02-24

使っている参考資料

  • ヒレガス本第4版
    • 何かほとんど本に書いてあることの写しみたくなっている…

outletとtarget、actionなど

  • outlet

    • コードの側から影響を与えたいオブジェクトへのポインタ
  • action

    • ユーザーがタップなどしたボタンなどのオブジェクトから送られるメッセージ
  • target

    • actionを送る先のオブジェクト。ViewControllerの場合が多そう。File's Ownerとか。

stackとheap

  • stack
    • メソッドや関数が実行されたときにメモリが確保される場所
  • heap
    • クラスにallocメッセージが送られたときにメモリが確保される場所

ポインタ変数とオブジェクトの所有権(Object Ownership)

  • ポインタ変数はその変数が指し示すオブジェクトの所有権を有している。

  • オーナーがいないオブジェクトはいずれ破棄される。 <-> オーナーがいると破棄されない。

    • まだ参照されているオブジェクトを破棄することは premature deallocationと呼ばれる。dangling pointerとかdangling referenceとして知られている。

どのようにしてオブジェクトはオーナーを失うか

  • 該当オブジェクトを参照していた変数が他のオブジェクトを参照するようになったとき
  • 該当オブジェクトを参照している変数にnilがセットされたとき
  • 該当オブジェクトのオーナー自体が破棄されたとき
  • コレクション内の該当オブジェクトがそのコレクションから取り除かれたとき

上記の状況でオーナーを失うことが直ちにオブジェクトの破棄に繋がるわけではない
- 他の変数が該当オブジェクトを参照していればまだそのオブジェクトは維持される

Ownership chains

  • 大元のオブジェクトが破棄されれば、そこから参照されているオブジェクトが芋づる式に破棄されていく

Strong and Weak References

  • ポインタ変数がオブジェクトを参照しているとき、そのオブジェクトはオーナーを持っていて、維持される。
    • これをstrong referenceという
  • オブジェクトを参照だけして所有権を持たないようにする変数もある。
    • これをweak referenceという
  • strong reference cycle (retain cycle)を回避するのにweak referenceは役に立つ
    • strong reference cycle (retain cycle)とは、二つ以上のオブジェクトがお互いのstrong referenceを持っているときに起こる
      • こうなるとこのオブジェクトがARCで破棄されなくなるため、メモリリークの原因になる
      • 片方の参照をweakにする必要が出てくる
      • オブジェクトの親子関係を考えてweakにする方を決める
      • 子が親へのポインタを必要としたら、そのポインタはweakにしないといけない

プロパティ

  1. Multi-threading attribute
    • マルチスレッドが関わってくるかそうでないかの値
  2. Read/write attribute
    • readwritereadonlyかの違い
    • デフォルトはreadwrite
  3. Memory management attribute
    • strong, weak, copy, unsafe_unretainedなど
      • assignはARCより前の語。
    • デフォルト値はstrong
      • デフォルト値は変わることがあるので宣言を明示するのが定石。
    • 参照のタイプを示している
    • オブジェクトをポイントしていないプロパティはメモリ管理する必要が無いので、常にunsafe_unretainedである
      • weak referenceとは違い、参照が指し示しているオブジェクトが破棄されたときにunsafe_unretained referenceは自動でnilがセットされるわけではない。
      • non-object propertyの場合、unsafe_unretainedがデフォルト値。
    • NSStringとかNSMutableArrayみたいなmutable classを持つクラスのインスタンスをプロパティが指し示すときは、メモリ管理属性はcopyをセットすべき。

プロパティのカスタムアクセサ

カスタムアクセサを実装すると挙動を変えられる。
- オーバーライド的な感じで書けばいい。
- 実装しているとデフォルトのアクセサは作られない
- getterとsetterを両方カスタムのものにすると、コンパイラはプロパティのインスタン変数を作らない
- 必要なときは自分で宣言する必要あり

ViewとView階層

View Hierarchy

  • 全てのアプリケーションはUIWindowのインスタンスを一つ持っていて、これがアプリケーション内の全てのViewのコンテナになっている

  • View Hierarchyが作られると、スクリーンにそれが描画される。そのプロセスは以下の2ステップに分解できる

    • 階層化の全てのView(windowを含む)は自身を描画する。CALayerのインスタンスである自身のlayerに自身をレンダリングする。
    • 全てのViewのlayerはスクリーン上で一つにまとめられる。

Viewとframe

  • viewのframeはsuperviewに対するsubviewのサイズとポジションを決める
    • よってviewは常に長方形
  • View ControllerはアプリケーションのView階層のある一部のセットを制御するオブジェクト

drawRect:を使ってカスタム描画

  • drawRect:メソッドを用いてViewのlayerにレンダリングする
  • boundsプロパティはViewが描画するエリアを決める長方形(rectangle)である
  • frameboundsは異なった目的がある
    • frameは、自身以外のView階層に対するViewのlayerをレイアウトして一つにまとめる時に使われる
    • boundsは、自身のViewのlayerの境界内で描画を詳細にレイアウトするレンダリングのステップの間で使われる

デベロッパードキュメントの使い方

  • Xcodeのメニュー -> Help -> Documentation and API Reference
    • ショートカットキーはOption-Command-?
      • Shiftとか使わないとでないかもね

For the More Curious: Core Graphics

  • drawRect:メソッドはUIImage, UIBezierPath, NSStringをだいたい使う。
    • これらのクラスは、drawRect:が実行されたときにpixelを描画するメソッドを少なくとも一つは持っている。
  • 描画はCore Graphicsフレームワークの領分である

Views: Redrawing and UIScrollView

  • ユーザがviewにタッチしたとき、そのviewにtouchesBegan:withEvent:メッセージが送られる

クラス拡張 (Class Extensions)

  • ヘッダでのプロパティ宣言とクラス拡張でのプロパティ宣言の違い
    • ヘッダは他のクラスから見える。つまり、外から見えて欲しいものを宣言する
    • あるクラス内部のみで使われるプロパティを宣言するときはクラス各町内で宣言する
  • クラス拡張は通常、メソッド定義より前に書く

UIScrollView

  • 通常、UIScrollViewはスクリーンより大きいviewを使いたいときに使う
  • UIScrollView.contentSizeはView自体の大きさ。表示している大きさはUIScrollView.frame.size

View Controllers

  • View Controllerはビュー階層を管理する
    • 階層を構成するViewオブジェクトを作る
    • 階層下のViewオブジェクトに関わるイベントをハンドリングする
    • windowに階層を加える
  • UIViewControllerのサブクラスは@property (nonatomic, strong) UIView *view;というプロパティを継承している

    • このView Controllerのビュー階層のルートであるUIViewインスタンスを指し示す
  • View Controllerのビューは必要になるまでスクリーン上に現れない

    • View Controllerが自身のビュー階層を作る方法は二通りある
      1. プログラムを書く。UIViewControllerloadViewメソッドをオーバーライドする
      2. Interface Builderを使ってNIBファイルをロードする

root view controllerを設定する

  • windowにview controllerのview階層を追加するUIWindows's setRootViewController:メソッド
  • XIBファイル内で作られたviewオブジェクトと実行中のアプリケーション内のview controllerを関連づけるときは、File's Ownerが関わってくる

  • NIBのロードはtwo-partプロセス

    • XIBにアーカイブされた全てのオブジェクトをインスタンス化し、NIBをロードするオブジェクトをFile's Ownerへ落とし込み、用意されたコネクションを確立する
  • XIBファイルとアプリを繋げるときにやること

    • File's Ownerのクラスを指定する
      • だいたいViewControllerのことが多い
    • File's OwnerのoutletとViewをControl-Clickなどで繋げる
    • ButtonなどUIViewのサブクラスのインスタンスから対応するactionにControl-dragなどで繋げる
  • outletをweakで宣言するのはiOSの以前のバージョンからの慣習

designated initializer of UIViewController

  • View Controllerが初期化されるときにNIBの名前がnilだったら、View Controllerは自身のクラス名が付いたNIBファイルを探す

Loaded and Appearing Views

  • viewは必要になるまでロードされない
    • この遅延ロードの恩恵を受けるには、initWithNibName:bundle:内でview controllerのviewプロパティにアクセスしないこと
  • subviewにアクセスするのは主に2つのやり方がある。
    • viewDidLoadメソッドをオーバーライドする。この時、spot lazy loadingすることになる
    • UIViewControllerviewWillAppear:メソッドを使う
      • 該当するviewがwindowに追加される直前にview controllerにこのメッセージが送信される
    • 違い
      • アプリケーションが動いているときに一度だけ設定が実行されて欲しいときはviewDidloadを使用
      • view controllerがscreenに現れる度に設定が実行されて欲しいときはviewWillAppearを使用

Interacting with View Controllers and Their Views

  • application:didFinishLaunchingWithOptions:はアプリケーションが起動したときに一度だけ呼び出される。他のアプリに移ってから戻っても再び呼ばれることはない
  • initWithNibName:bundle:はUIViewControllerのdesignated initializerである。view controllerのインスタンスが作られたときに一度だけ呼び出される。同じview controllerのインスタンスが作り出される度に呼び出される。
  • loadViewはview controllerのviewをプログラミングで作る時にオーバーライドするもの
  • viewDidLoadはNIBファイルをロードしてviewを設定するときにオーバーライドするもの。view controllerのviewが作られた後に呼び出される
  • viewWillAppearはview controllerがスクリーン上に移動する度毎回呼び出される

For the More Curious: Key-Value Coding

  • KVCは、名前でプロパティの値を設定したり取得したりすることが出来るメソッドのセットでNSObjectで定義されている

とりあえず訳が分からないので飛ばす。

For the More Curious: Retina Display

  • Core Graphics functionを使って描画しているときはRetina、非Retina端末で見え方が変わってくることに注意
  • Retina用の画像は末尾を@2xにする

Delegation and Text Input

UIResponder

  • UIResponderはUIKitフレームワークの抽象クラス

    • 以下のスーパークラス
      • UIView
      • UIViewController
      • UIApplication
    • イベントをハンドリングするメソッドを定義している
      • サブクラスでこれらのメソッドをオーバーライドすればイベントの反応の仕方をカスタマイズできる
  • タッチイベントはタッチされたビューに該当イベントが直接送られる。(Chapter5参照)

  • タッチイベント以外のイベントではどうか?

    • タッチイベント以外のイベントに反応するのが誰かを示すfirstResponderというポインタをUIWindowは持っている
    • ビューにfirst Responderになって欲しいときはbecomeFistResponderメッセージを送る。するとキーボードが出現する
    • キーボードを隠したいときはresignFirstResponderメッセージを送る
  • 大半のビューはfirst responderにはなれない

    • 現在選択されているテキストフィールドやテキストビューからフォーカスを奪わない
  • キーボードの見た目はUITextInputTraitsというUITextFieldのプロパティのセットで決められている

      • autocapitalizationType
      • autocorrectionType
      • enablesReturnKeyAutomatically
      • keyboardType
      • secureTextEntry

Protocols

  • delegateを持っている全てのオブジェクトには、対応するプロトコルがあり、そのプロトコルはオブジェクトが自身のdelegateに送ることが出来るメッセージを宣言している

    • protocolは、JavaやC#でいうinterface
  • プロトコルはクラスではなく、単なるメソッド宣言のリスト

  • プロトコル内で宣言されたメソッドはrequiredかoptionalになる。デフォルトはrequired

  • optionalのメッセージを送る前に、オブジェクトは自身のdelegateにrespondsToSelector:メッセージを送ることで「そのメッセージを送っても大丈夫か?」と確認する

    • respondsToSelector:は全てのオブジェクトが実装している
      • 与えられたメソッドをオブジェクトが実装しているかを実行時にチェックするメソッドである
  • プロトコル内のメソッドがrequiredだったらメッセージはチェックされることなく送信される

    • もしdelegateが該当メソッドを実装していなかったらunrecognized selector exceptionが投げられてアプリがクラッシュする

Adding the Labels to the Screen

  • textShouldreturn:メソッドを使って、テキストフィールドで決定ボタンを押したりしたときの動作を決めている

モーションエフェクト(Motion Effects)

  • UIInterpolatingMotionEffectクラスを使ってモーションエフェクト関係の機能を強化できる
  • モーションエフェクトをテストするには、デバイス上でアプリを実行する必要がある

デバッガを使う(Using the Debugger)

  • デバッガ使用の一つのやり方はブレイクポイントをセットすること
  • ブレイクポイントをセットしてアプリを実行してブレイクポイントのところで止まったとき、ナビゲーションエリアにはスタックトレースが表示され、はっきりした黒字で表示されているのは自作のコード、グレーになっているのはApple関連のコードである

Stepping through code

  • どこにブレイクポイントを設定したか分からないときは、breakpoint navigatorの中を見るとプロジェクト内のブレイクポイントの一覧を見ることができる

Setting an exception breakpoint

  • アプリをクラッシュさせたり例外が投げられる箇所に自動的にブレイクポイントを設定できる
    • navigator areaで最下部の+アイコンをクリックし、"Add Exception Breakpoint"を選択する

For the More Curious: main() and UIApplication

  • 全てのアプリケーションはUIApplicationインスタンスを一つ持っている。このインスタンスはrun loopをメンテナンスする(maintaining the run loop)役目があり、一度アプリケーションのオブジェクトが作られるとこのrun loopは必然的にinfinite loopになる:

    • つまり、実行しているスレッド(?)(executing thread)はmain()には永久に帰ってこない
  • もう一つUIApplicationMain関数が行うことは、UIApplicationのdelegateとして受け取られる(?)(serve as the UIApplication's delegate)クラスのインスタンスを作ることである

  • 全てのアプリケーション内のrun loopに加えられる最初のイベントは、アプリケーションに自身のdelegateへメッセージを送るよう促すspecial "kick-off" eventである

    • そのメッセージとはapplication:didFinishLaunchingWithOptions:である

Silver Challenge: Pinch to Zoom

UITableとUITableViewController

  • ユーザの連絡帳内の人物一覧やApp Store内のbestsellingアイテムの一覧を表示する時は、UITableViewがその仕事を行う

  • UITableViewが表示するのはたくさんの行が加わった一列のデータである

UITableViewController

  • UITableViewはview objectである。
    • アプリケーションロジックやデータは扱わない
  • UITableViewを使う時は、このTableがアプリ内で機能するためには他に何が必要が考えないといけない

    • UITableViewはスクリーンに表示されるようにするためにview controllerを必要とするのが普通である
    • UITableViewはdata sourceを必要とする
      • UITableViewのdatasourceには、UITableViewDataSourceプロトコルに合致している限りはObjective-Cのどんな型のオブジェクトでもなれる
    • UITableViewは通常、UITableViewに関わるイベントを他のオブジェクトに知らせることが出来るdelegateを必要とする。delegateはUITableViewDelegateプロトコルに合致している限りはどんなオブジェクトでもなれる。
  • UITableViewControllerクラスのインスタンスは以下三つの役割全てを満たすことが出来る

    • view controller
    • data source
    • delegate
  • UITableViewControllerのviewは常にUITableViewのインスタンスであり、UITableViewControllerはUITableViewをどう用意するか、どう見せるかといったことを扱う

  • UITableViewControllerが自身のviewを作ったとき、
    UITableViewのdataSourceとdelegateインスタンス変数は自動的にUITableViewControllerを指すようセットされる

Subclassing UITableViewController

UITableView's Data Source

  • Cocoa TouchにおいてUITableViewに行(rows)を与えるプロセスは典型的な手続き型プログラミングタスクとは違う

    • 手続き型のデザインでは、何を表示すべきかテーブルビューに伝える
    • Cocoa Touchでは、何を表示すべきかテーブルビューが他のオブジェクト(=自身のdataSource)に訪ねる
  • static変数はメソッドが実行し終わっても破棄されない

    • global変数みたいだけど、スタック上には保持されていない
  • @classディレクティブは「該当クラスは存在するけどコンパイラはそのクラスの詳細を現在のファイルで知る必要は無いよ」とコンパイラに伝えてくれる

    • @classディレクティブを使うとコンパイルが結構速くなる
      • 一つファイルを変えても再コンパイルするファイルが少なくなるから。

Implementing data source methods

  • UITableViewが表示するものを知りたいとき、UITableViewはUITableViewDataSourceプロトコルで宣言されたメッセージ群からメッセージを送る
    • tableView:cellForRowAtIndexPath:
    • tableView:numberOfRowsInSection:
  • UITableViewが自身を表示したいときはいつもdataSourceにこれらのメッセージ群(required methodsに加え、実装されたoptional methods)を送る

  • Table viewはセクションに分けられる。それぞれのセクションはそれ自身特有のset of rowを持っている

UITableViewCells

  • table viewのrowはviewはそれぞれviewであり、これらはUITableViewCellのインスタンスである
  • cellは一つsubviewを持っており、contentViewという。contentViewは該当cellのコンテンツのsuperviewである
  • UITableViewCellの実体(The real meat)はcontentViewのsubview3つである。2つはtextLabeldetailTextLabelと名前の付いたUITableViewCellのプロパティで、3つ目はimageViewという名前のUIImageViewのsubviewである。
  • UITableViewCellStyleに値を設定するとUITableViewCellの表示のされ方が変わってくる

Creating and retrieving UITableViewCells

  • UITableViewCellのインスタンスを表示するとき、表示から外れたやつは再利用のためのプールに押し込められ、data sourceがそこから必要になったセルを再利用する。
  • 返ってくるcellの型に注意すべし。どんなプロパティとメソッドを持っているかも。
  • data sourceがtable viewに再利用できるcellを求めるとき、data sourceは文字列を渡し「このreuse identifierを持っているcellを必要としている」と伝える。
    • reuse identifierは慣習としてcellクラスの名前になることが常である

Code Snippet Library

Editing UITableView

Editing Mode

  • UITableViewはeditingプロパティを持っている
    • editingYESの時、 UITableViewはediting modeになる
    • editing modeになるとtable内のrowをユーザが操作できる
      • rowの中身を編集することは出来ない
  • table viewは'header'という語を二つの意味で使う
    1. table header
    2. section headers
  • 同様に、table footerとsection footersがあり得る

  • weak referenceはトップレベルのオブジェクトに(直接的、もしくは間接的に)所有されているオブジェクトに使う

  • XIBファイルをマニュアルでロードするときはNSBundle を使う

    • このクラスはアプリケーションとアプリケーション内で生きているapplication bundleの間のインターフェースである
  • よくあるパターン

    • 必要になるまでオブジェクトを作らない(Lazy Instantiation)
  • UITableViewのeditingプロパティをトグルすることも出来るが、UITableViewControllerもeditingプロパティを持っている

    • UITableViewControllerインスタンスは自身のeditingプロパティとマッチするように、自身のtable viewのeditingプロパティをセットする
    • view controllerにeditingプロパティをセットするには、view controllerにsetEditing:animated:メッセージを送る

Adding Rows

  • 実行時にtable viewに行(row)を加えるには2つのありふれた(common)インターフェースがある

    1. table viewのcellの上のボタン
      • だいたいレコードを追加するためのもの
      • 新しく会った人の情報を連絡帳アプリを使って記録するときなど
    2. 緑色の+の印がついたcell。
      • レコードに新たなフィールドを追加するためのもの
      • ある人の誕生日の情報を連絡帳アプリ内で追加するときなど。
  • table viewが表示すべき行(row)の数を決めるのはUITableViewのdataSourceである

Deleting Rows

  • table viewがrowを削除する前、table viewは自身のdata sourceに提案された削除に関するメッセージを送信する。そしてtriggerを引っ張る(pulling the trigger)前に確認メッセージ(confirmation message)を待つ

  • cellを削除するとき、2つのことをしないといけない

    1. UITableViewからrowを削除する
    2. rowにひもづいたBNRItemをBNRItemStoreから削除する
  • removeObjectIdenticalToメソッドはこのメソッドに渡されたオブジェクトと全く同じ(同等)のオブジェクトの時のみオブジェクトを削除する

  • tableView:commitEditingStyle:forRowAtIndexPathがdata sourceに送られるとき、2つのextra argumentsが渡される。

    1. UITableViewCellEditingStyle
      • 今回の場合、UITableViewEditingStyleDelete
    2. table内のrowのNSIndexPath

Moving Rows

  • UITableView内のrowの順序を変えるためにはUITableViewDataSourceプロトコルから別のメソッドを使う

    • tableView:moveRowAtIndexPath:toIndexPath:メソッド
  • rowを削除するにはdeleteRowsAtIndexPaths:withRowAnimation:メッセージをUITableViewに送って削除を確認する(to confirm the deletion)
    しかし、rowを移動するときは確認(confirmation)は必要ない。

    • table viewがそれ自身のauthorityによってrowを移動させ、その移動を自身のdata sourceに知らせる
      • その時tableView:moveRowAtIndexPath:toIndexPath:メッセージを送る

UINavigationController

  • 設定アプリみたいな階層構造のビューを持ったインターフェースをdrill down interfaceという

UINavigationController

  • アプリがmultiple screens of informationを提供するとき、UINavigationControllerはそのscreensのスタックを保持する

    • それぞれのscreenはUIViewControllerのviewであり、スタックはview controllersのarrayである
    • UIViewControllerがスタックのトップなら、UIViewControllerのviewはvisibleになる
  • TITabBarControllerと同じく、UINavigationControllerはviewControllers arrayを持っている

    • root view controllerはこのarrayのファーストオブジェクトである
    • topViewControllerプロパティはスタックのトップへのポインタを保持している
  • UINavigationControllerはUIViewControllerのサブクラスのため、自身のviewを持っている

    • このviewは常に2つのsubviewを持っている
      • UINavigationBar
      • the view of topViewController
  • iOSアプリを書くときは、それぞれのUIViewControllerをそれ自身が小さな世界として扱うことが大切である

An Additional UIViewController

  • 3つの別個のステップ

    • interface fileにoutletを加える
    • XIB file内でインターフェースを設定する
    • それらを繋げる
  • 便利なショートカット

    • Command-Return-Option-Return = アシスタントエディタ表示
    • Command-Return = スタンダードエディタ表示
    • Command-Option-0 = ユーティリティエリアの表示・非表示切り替え
    • Command-0 = ナビゲータエリアの表示・非表示切り替え
  • simulated metricsを見るためには、root level viewを選択した状態でattribute inspectorを開き、Simulated Metricsの中から適切な物を選ぶ

  • ファイルを行ったりきたりするのに使うショートカット

    • ダブルクリック = 新しいタブでファイルを開く
    • Command-T = ブランクタブを開く
    • Coomand-Shift-}, Command-Shift-} = タブ移動

Navigating with UINavigationController

  • UINavigationControllerを使用するとき、そのスタックに納められる可能性のあるview controller全てを単純に保持することは出来ない

    • navigation controllerのviewControllers arrayは動的である
    • navigation controller以外のオブジェクトがBNRDetailViewControllerのインスタンスを作る必要があり、そのインスタンスをスタックに追加する責務を負っている
  • このオブジェクトは以下2つの要件を満たす必要がある

    1. BNRDetailViewControllerをいつスタックに追加する必要があるのか知っていること
    2. navigation controller messages、つまりpushViewcontroller:animated:メッセージを送るためにnavigation controllerへのポインタを必要としていること
  • view controllerが次のview controllerをpushするのは良くあるパターン。root view controllerは次のview controllerを作るのが良くあるし、その作られたview controller(?)は更に次のview controllerを作る。

  • 新しくiOSを始めるプログラマの多くはview controller間でどのようにデータをやりとりするかについて苦労する。

    • root view controllerに全てのデータを持たせ、そのデータのサブセットを次のUIViewControllerに渡す(今君がしたように)のがこのタスクをこなすのに簡潔で効率の良いやり方である。

Appearing and disappearing views

  • UINavigationControllerがviewをswapしようとするとき、UINavigationControllerは二つのメッセージを送信する。

    1. viewWillDisappear
      • stackから外れ(popped off)ようとしているUIViewControllerに送られるメッセージである。
    2. viewWillAppear
      • stackのtopになろうとするUIViewControllerに送られるメッセージである。
  • endEditingメッセージがviewに送られた時、そのview自身、もしくはsubviewのどれかが現状first responderであり、そのfirst responderステータスを放棄しようとする。そしてキーボードは消える。

UINavigationBar

  • UINavigationBarが表示すべきなのは、UINavigationControllerのstackのtopに現在いるUIViewControllerへの説明的タイトル(descriptive title)である。

  • 全てのUIViewControllerはUINavigationItem型(?)のnavigationItemプロパティを持っている。

    • しかし、UINavigationBarと違い、UINavigationItemはUIViewのサブクラスではないので、スクリーン上に現れることが出来ない。
    • その代わり、描画する必要のある中身と一緒のnavigation barを提供している
  • 通常は、UINavigationItemは空である。最も基本的なレベルにおいて、UINavigationItemは簡素なtitle文字列を持っている。UIViewControllerがnavigation stackのトップに移動し、titleプロパティとして適切な文字列をnavigationItemが持っているとき、navigation barはその文字列を表示する。

  • UINavigationItemと同じように、UIBarButtonItemはUIViewのサブクラスではない。その代わり、UINavigationItemは自身を設定するのに使用している情報をカプセル化している。同様に、UIBarButtonItemもviewではないが、UINavigationBar上にある一つのボタンがどのように表示されるべきかという情報を持っている。(UIToolbarも自身を設定するのにUIBarButtonItemのインスタンスを使っている)

  • UINavigationItemの3つ目のカスタマイズ可能なエリアはUINavigationItemのtitleViewである。文字列をタイトルとして使うことも出来るし、navigation itemの中央にUIViewのサブクラスを鎮座させることも出来る。

  • bar button itemはUIControlのtarget-actionメカニズムと同様の働きをするtarget-actionペアを持っている; タップされると、targetに対してactionメッセージを送る。

  • このactionはSEL型の値として渡される。SEL型はselectorへのポインタであり、selectorはあらゆるコロンを含んだ全てのメッセージであることを思いだそう。@selector()は返り値の型、引数の型、引数の名前を気にかけないことを覚えておこう。

Camera

Displaying Images and UIImageView

  • UIImageViewは自身のcontentModeプロパティによって画像を表示する。このプロパティが決定するのは、image viewのframe内のコンテンツをどこに配置するか、どうやってリサイズするかということである。contentModeに対するUIImageViewのデフォルト値はUIViewContentModeScaleToFillである。この値は画像をimage viewの境界にちょうどマッチさせるように調整する。

  • デフォルトでは、XIBファイル内で作られるUIToolbarの新しいインスタンスはUIBarButtonItemとともにやってくる。

Touch Events and UIResponder

Touch Events

  • UIResponderのサブクラスとして、4つの別個のtouch eventsを扱う4つのメソッドをUIViewはオーバーライドできる。

    1. スクリーンに指がタッチしたとき
      • (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    2. スクリーン上を指が移動したとき
      • (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
    3. スクリーンから指が離れたとき
      • (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
    4. 電話が来たときなど、touchが終わる前にsystem eventがtouchを中断した(interrupts)ときなど
      • (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
  • 指がスクリーンに触れたとき、UITouchのインスタンスが作られる。
    指が触れたUIViewにはtouchesBegan:withEvent:メッセージが送られ、UITouchはtouchesのNSSetにセットされる。

  • スクリーン上を指が動き回るとき、touch eventはアップデートされ、スクリーン上の指の現在位置を保持する。そして、touchが始まったのと同じUIViewにtouchesMoved:withEvent:メッセージが送られる。このメソッドに引数として渡されるNSSetは、指がスクリーンにタッチしたときに生成されるのと同じUITouchを保持する。

  • 指がスクリーンから離れたとき、touch objectはアップデートされ、指の現在位置を保持するのはこれが最後である。タッチが始まったviewにはtouchesEnded:withEvent:メッセージが送られる。このメソッドが実行し終わったとき、UITouch objectは破棄される。

  • この情報からtouch objectsの働きに関する結論が以下のように得られる。

    • ひとつのUITouchはスクリーン上の一つの指に対応する。このtouch objectは指がスクリーン上にある限り生き続け、その指の現在位置を絶えず保持する。
    • 指が最初に触れたview(The view that the finger started on)はその指に対する全てのtouch eventメッセージを受け取る。もし最初に触れたUIViewのframeから指が移動して外に出た場合、そのviewはtouchesMoved:withEventtouchesEnded:withEvent:メッセージを受け取る。つまり、touchがview上で始まると、そのviewはそのtouchが生きている間、そのtouchを保持するということである。
    • UITouch objectのreferenceを保持する必要はないということ。アプリケーションはtouch objectの状態が変わったときにそのtouch objectにアクセスする手段を与えてくれる。

Creating the TouchTracker Application

Drawing with BNRDrawView

Turning Touches into Lines

Handling multiple touches

For the More Curious: The Responder Chain

  • UIResponderはタッチイベントを受け取ることが出来る。

    • UIViewはUIResponderのサブクラスの一つ。他にもUIViewController、UIApplication、UIWindowsなど色々ある。
  • UIViewControllerへ「直に」タッチイベントを送ることは出来ないが、view controllerはresponder chainを通してイベントを受け取ることが出来る。

  • 全てのUIResponderはnextResponderと呼ばれるポインタを持っていて、これらのオブジェクトが集まってresponder chainを作る。

  • UIResponderはどのようにしてイベントを「扱わない」ようにするのか?

    • UIResponderは同じメッセージをnextResponderに送る。この仕組みは、touchesBegan:withEvent:のようなメソッドのデフォルト実装が行うのと同じである。
    • そのため、メソッドがオーバーライドされていなければ、UIResponderのnext responderがタッチイベントを処理することになる。もしapplication(responder chainの最後のオブジェクト)が該当イベントを処理しなければ、そのイベントは破棄される。

For the More Curious: UIControl

UIGestureRecognizer and UIMenuController

  • よくあるジェスチャーを検出するコードを自前で書く代わりに、UIGestureRecognizerのインスタンスを使用することが出来る。

  • UIGestureRecognizerは、viewによって処理されている途中のタッチをinterceptする。

  • UIGestureRecognizer自体をインスタンス化するわけではなく、代わりにUIGestureRecognizerのサブクラスがあり、
    特定をジェスチャーを認識するものを使うとよい。

Detecting Taps with UITapGestureRecognizer

Multiple Gesture Recognizers

UIMenuController

UILongPressGestureRecognizer

UIPanGestureRecognizer and Simultaneous Recognizers

For the More Curious: UIMenuController and UIResponderStandEditActions

  • 通常、UIMenuControllerは表示されるときに「編集」メニューをユーザに見せる責務を負っている。

For the More Curious: More on UIGestureRecognizer

Debugging Tools

Introduction to Auto Layout

Universalizing Homepwner

The Auto Layout System

  • Auto Layout システムは一つのviewに対して別の長方形と協調する。この長方形のことをalignment rectangleという。

  • constraintは、view階層内に特定のrelationshipを定義し、一つもしくはそれより多くのviewに対するlayout attributeを決定する。

0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up