*

Xcode(Objective-C)のデリゲートとプロトコルの使い方[前編]

公開日: : 最終更新日:2014/09/05 Objective-C


スポンサードリンク



Xcode(Xcode5でも同様)でアプリ開発をしていて、少し複雑な事をしようとするとデリゲートと言う概念にほぼぶつかります。

当然利用する言語はObjective-Cなのですが、結構経験年数が長くて、ある程度の数の言語を触ったことがある方
がキーワードを聞くと、一番に思い浮かぶのはやはりあれですよね。C#のデリゲート(C#使いじゃない方すみません・・・)

Javaではデリゲートの考え方が無いです。あらもうJava8まで行ってる。それも最近ですねリリース。
大刷新リリースですね・・・、コアスキルがJava関連だったのはもう6年ぐらい前で、Java6が出てたかどうかぐらいだったと・・・
触ってみたいですね、アンドロイド向けのスマートフォンアプリ開発をやれば使える。いや、Andriod SDKがすんなり動くのか?

と関係ない方向に話がそれて行っているので戻ってりますが、
Javaもインターフェースを利用することでデリゲートに似た動作が実現可能です。
しかし、動作を委譲するクラスがそのインターフェースを実装しないといけないので自由度や、変更に弱い(一人開発であれば関係ないか・・・)との問題点があります。

その問題点を認識してC#は言語の作成段階から、言語仕様としてデリゲートとの概念を取り入れました。

Xcode(Objective-C)のデリゲートの使い方[前編]では、C#のデリゲートを簡単に説明した後に、C#とXcodeでのデリゲートの違いの説明と利用例を記載させていただきます。

説明前の段階では、少し難しいですが、
C#のデリゲートは単一のメソッドに関する処理の委譲で、Objective-Cのデリゲートは複数処理(プロトコルデリゲート)を、そのデリゲート先のクラスに委譲する仕組みとなっています。

なお、Xcode(Objective-C)のデリゲートの使い方[後編]では、デリゲートの定義方法とその利用について記載させていただく予定です。

利用しているXcodeはXcode5(5.1 iOS7対応バージョンの統合開発環境)となります。

本エントリーの内容は以下の通りとなります。

  1. C#のデリゲートの説明
  2. Xcodeでのデリゲートの説明
  3. Xcodeでのデリゲートの利用例

 

C#をご存知でない方は「1 C#のデリゲートの説明」は読み飛ばしていただいても問題ないですが、
処理を委譲する単純な例(C#)の説明のあとに、それよりも複雑なObjective-Cでのデリゲートを見ていただいた方が理解しやすいと感じています。

1 C#のデリゲートの説明

デリゲートの定義方法

C#のデリゲートの場合、まず利用するデリゲートのシグネチャ(返却値、引数、デリゲートの名前)を定義します。
定義例:delegate int SampleDele(int x, int y);
ですと、SampleDeleと言う名前のデリゲートで、返却値がint、引数は2つで両方ともintを定義したことになります。

デリゲートの利用サンプル

コンソールで動作するサンプルを作成いたしました。
csファイルはProgram.csとDelegateRunner.csのみです。
Program.csは以下の様になります。
14行目でDelegateRunnerのクラスを作成し、
DelegateRunnerのRunメソッドを
17行目でHogeHogeデリゲートを第3引き数に指定して呼び出し、
19行目でHogeデリゲートを第3引き数に指定して呼び出しています。

DelegateRunner.csは以下の様になります。
DelegateRunnerのRunメソッドでは第3引数のdelegateFuncにx,yを渡して呼び出して、その結果をリターンしています。

この様に、実際の処理を行うメソッドのシグネチャだけは、この形でとデリゲート(SampleDele)として定義しておき、実際の処理はSampleDeleと同じシグネチャのHogeHogeメソッド、もしくはHogeメソッドに委譲するとの形が実現されています。
この例の場合はMainからのsampleOne.Run呼び出し時にデリゲートをセットしていますが、DelegateRunnerのインスタンス変数としてSampleDele型のメンバーを定義しておき、コンストラクタやセッター等でセットするとの動きを実現すればより、処理の委譲という形に近くなると思います。

実行したときの結果画面は以下の様になります。
実行結果

2 Xcodeでのデリゲートの説明

前述のC#の例で見ていただいたデリゲートは、任意のメソッドの様な物をデリゲートとして扱い、実処理をそのメソッドに委譲するとの物でした。

XcodeにおけるデリゲートはJavaやC#のインターフェースをC#のデリゲートの様な物として定義しているように思えます。
メソッドをデリゲートするのでは無く、インターフェースをデリゲートするイメージです。
実際は既定の動作が実装されているのでクラスなんでしょうけど・・・

以降では、
iOS Developer Libraryの「UIAlertViewDelegate Protocol Reference」を例として進めます。
Protocolというキーワードが出て来ましたが、これについては後編で説明させていただきます。
UIAlertViewDelegateというデリゲートが有る事だけに注目してください。

UIAlertViewDelegate

このページで注目していただきたいのは「Tasks」です。
スクリーンショット 2014-03-24 17.39.31

画像に記載されているメソッドの概要は以下の様になります。

メソッド名 意味 UIViewContentMode
–alertView:clickedButtonAtIndex: イベントハンドラ ボタンがタップされた時に呼び出される。
–alertViewShouldEnableFirstOtherButton: 動作のカスタマイズ 右側のボタンを有効にするかしないかを決定する。入力されている文字によって表示or非表示なんかも制御できる。有効にする場合はYESを返却
–willPresentAlertView: 動作のカスタマイズ アラート表示直前に呼び出される。
–didPresentAlertView: 動作のカスタマイズ アラート表示直後に呼び出される。
–alertView:willDismissWithButtonIndex: 動作のカスタマイズ アラート画面が閉じる直前に呼び出される。
–alertView:didDismissWithButtonIndex: 動作のカスタマイズ アラート画面が閉じた直後に呼び出される。
–alertViewCancel: キャンセル時の動作 キャンセルされた時に呼ばれる。

UIAlertView作成時にDelegateとしてselfを指定し、動作を変更したい任意のメソッドを実装(オーバーライドの方がしっくり来ますが・・・)することで、UIAlertViewDelegateを利用した動作の変更が可能となります。
実際の利用例は次節で記載させていただきます。

本節では、UIAlertViewに対するデリゲートであるUIAlertViewDelegateを例としましたが、当然他のUIコンポーネントに対しても同様のデリゲートが既に定義されています。

3 Xcodeでのデリゲートの利用例

実際にUIAlertViewDelegateを利用したアイフォン(iPhone)アプリを開発しながら利用方法の説明を行います。

利用例を説明するためのアプリの準備

今回はUIAlertViewDelegateの利用例ですので、「Simple View Applycation」テンプレートのプロジェクトを作成して利用します。
「Product Name」にはUIAlertViewDelegateSample、「Compamy Idenfifier」にはcom.exampleを指定してプロジェクトを作成してください。
ターゲットデバイスはデフォルトのままでiPhoneとしてください。

タップ時にアラートを表示するボタンを配置

ボタンの配置やアウトレット、アクション接続については「Xcode5で画面コンポーネントを利用するための基本」をご覧ください。

Main.storyboardを開いて、ユーティリティエリアからボタンを配置します。
スクリーンショット 2014-03-26 11.28.54

ボタンのアウトレット接続

配置したボタンのアウトレット接続を行います。NameはalertButtonとしてください。
スクリーンショット 2014-03-26 11.39.46

ボタンタップ時の処理のアクション接続

ボタンタップ時の処理のアクション接続を行います。NameはtapButtonとしてください。
スクリーンショット 2014-03-26 11.45.25

ボタンタップ時の処理のアクションの実装

ViewController.mにアクション接続時に作成された- (IBAction)tapButton:(id)senderメソッドの実装を行います。
行いたい処理としては
・アラート画面の作成
・アラート画面の表示
となります。

実装後のViewController.mは以下の様になりました。
注目していただきたい部分はdelegate:selfとの記述です。
作成するUIAlertViewのデリゲートは自分自身(ViewController)であるとの指定を行っています。

UIAlertViewの各種引数については一目で意味が分かるようにしているつもりですが、ご不明な点がございましたら
iOS Developer Libraryの「UIAlertView Class Reference」をご覧ください。

とりあえず、この時点で一度実行してみます。
ショートカットキーは「Command」ボタン+「R」ボタンです。

ショートカットキにつきましては、「Xcode5を軽快に利用するためのショートカット[基本編]」とのエントリーを作成しておりますので、是非ごらんください。

実行後にボタンをタップすると以下の様になると思います。
スクリーンショット 2014-03-26 12.15.27

とりあえずここまでは思った通りですね。
「Command」ボタン+「.」ボタンのショートカットで実行を停止させておきましょう。

デリゲートの実装

このままではUIAlertViewの初期化時にdelegate:selfと、デリゲートとしてViewControllerを指定しているにも関わらず、デリゲートの処理を実装しておりませんので、実装いたします。といってもログ入れるだけですが。

本エントリーと直接関係ないのですが、Eclipseだとインターフェースを指定してダミー実装を生成する機能があったと思うのですが、Xcodeには無いみたいですね・・・、不便ですね。

UIAlertViewDelegateの定義からコピーして変更するのが一番早そうです。

と言う事でViewController.mでUIAlertViewDelegateを実装してみました。
UIAlertViewDelegateでは、7メソッド全てを実装しなくても良い定義となっております。
これについては、「Xcodeでデリゲートを使ってみる。[後編]」で説明させていただきます。

アプリを実行するとログには何も出力されず
Buttonボタンをタップすると
2014-03-26 14:26:56.887 UIAlertViewDelegateSample[1260:60b] willPresentAlertViewが呼ばれました。
2014-03-26 14:26:56.889 UIAlertViewDelegateSample[1260:60b] alertViewShouldEnableFirstOtherButtonが呼ばれました。
2014-03-26 14:26:57.450 UIAlertViewDelegateSample[1260:60b] didPresentAlertViewが呼ばれました。
が出力され、
キャンセルボタンを押すと
2014-03-26 14:34:33.588 UIAlertViewDelegateSample[1260:60b] buttonIndex=0がタップされました。
2014-03-26 14:34:33.589 UIAlertViewDelegateSample[1260:60b] willDismissWithButtonIndexが呼ばれました。
2014-03-26 14:34:34.110 UIAlertViewDelegateSample[1260:60b] didDismissWithButtonIndexが呼ばれました。
が出力されました。

予想通りの呼び出しタイミングですね。しかしalertViewCancelはどのタイミングで呼び出されるのでしょうか?
この答えは
iOS Developer Libraryの「UIAlertViewDelegate Protocol Reference」
にある以下の記述が相当します。

An alert view can be canceled at any time by the system—for example, when the user taps the Home button.

アラート画面が表示されていて、ホームボタンが押されたり、アプリの強制終了をiOSが行うタイミングのようです。後者は私がthe system-for exampleから類推して書いていますので、実際は違う可能性があります。

確認してみようと思い、アラート画面が表示させた状態で、ホームボタンを押してもalertViewCancelが呼び出されません。
うーーん、と思いググっていると
stackoverflowwにそれらしいスレッドがありました。
私の貧弱な英語力で読んだ結果ですが、appleが誤解を受けやすい説明を書いており、実際にアラート画面がシステムからキャンセルされた時に呼ばれるんだそうです。

ホームボタンで終わらせても対象アプリがバックグラウンドになるだけで、
再度フォアグラウンドになればアラート画面は表示されますよね。これではシステムからアラート画面をキャンセルしたことにはならないようです。

深みにハマって行きそうなの、alertViewCancelはとりあえず保留で・・・

ViewController.hについて

UIAlertViewの作成時にデリゲート先はViewControllerであるとの指定を行っていますので、本来であれば

ViewController.hは以下のようになるべきです。

本来は上記の様にUIViewController<UIAlertViewDelegate>
といった具合にUIAlertViewDelegateのデリゲートとして動作するクラスだと明示的に記載する必要があるのですが
UIAlertViewDelegateの場合は省略可能です。

以下のコードでも問題なく動作します。理由は調べてみましたが不明です。

前編の最後になりますが、UIViewControllerの継承クラスをデリゲートとするとの仕様(と言うか考え方)
はどうかと思います。だってデリゲートの処理はUIViewControllerとは本質的には関係ないし、まあ画面コンポーネントを参照できなくなるからここで良いかとは思いますが、結局多機能な画面を作成した時に、デリゲートの同じメソッド内での分岐が醜くなると思うのですが・・・
まあ、1画面でそんなに多くのことするなよってのがiOSのアプリの基本理念なんでしょうけど・・・

本エントリーの内容で十分理解いただけた方も、いただけなかった方も後編を読んで、再度本エントリーをお読みいただければ、より一層理解が深まると思います。

「Xcode(Objective-C)のデリゲートの使い方[後編]」

本エントリーは利用言語がObjective-Cの時のデリゲートの使い方を記載しております。
利用言語がSwiftの時の場合は
「Xcode(Swift)のデリゲートとプロトコルの使い方」をご覧ください。


スポンサードリンク

Googleアドセンス

Googleアドセンス




関連記事

Xcode5で画面コンポーネント(UIコンポーネント)配置して利用するための基本

iOSアプリケーションは当然ですが、画面がありますよね。 言わずもがなですが、iOS向けのアプ

記事を読む

Xcode5の「Auto Layout 」機能の使い方[基礎知識と制約(Align)の設定方法]

Xcode4から導入された「Auto Layout」ですが、使いこなせるようになるのは骨が折れます。

記事を読む

Xcode&Objective-Cの文字列処理をユニットテスト(XCTestフレームワーク)で確認する。[NSStringの比較]

前回は、NSStringの定義、分割、検索の各処理を確認しました。 二回目は、NSStringの比

記事を読む

Xcode5のEmpty Application templateでStoryboardを利用する。

Xcode5のEmpty Application templateでStoryboardを利用する方

記事を読む

iOS(Xcode6)におけるマルチスレッド処理の実装方法[iOSのマルチスレッド処理の概要]

iOSにおけるマルチスレッド処理の実装方法を数回に分けて説明させていただきます。 開発環境のXco

記事を読む

Objective-Cでコールバック処理を@Selectorで実現する方法

最近はSwiftばっかり読み書きしていますが、既存のライブラリをカスタマイズして使うことも多いので

記事を読む

Xcode&Objective-Cのまとめエントリー

エントリーもまずまず揃ってきたので、まとめのエントリーを作成しておこうと思います。 基本的には、各

記事を読む

Xcode5の「Auto Layout」機能の使い方[Pin制約の設定方法]

「基礎知識と制約(Align:アライメント)の設定方法」に引き続き、「Auto Layout」に必要

記事を読む

iOS(Xcode6とObjective-C)におけるマルチスレッド(非同期)処理の実装方法その2[GCD(Grand Central Dispatch)の利用]

本エントリーではGCD(Grand Central Dispatch)を利用したiOSのマルチスレッ

記事を読む

Xcodeの使い方[エディタエリアのテキストエディタ]

「Xcodeの使い方」に引き続き「 Xcode5のエディタエリアの使い方[テキストエディタの使い方]

記事を読む

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

動画で英語を学習できるiOSの無料アプリCapTubeをリリースいたしました。

個人では初となるiOSアプリをリリースいたしました。 何度もリジ

no image
Ruby on rails4系でBootstrapを利用するためのtips

MacでRuby on rails4系のBootstrapを利用しよう

no image
Java、Eclipse、JUnit関連のエントリーの移行のお知らせ

Java、Eclipse、JUnit関連のエントリーは http:/

iOS8開発者向けお勧め本紹介[詳細! Swift iPhoneアプリ開発 入門ノート Swift 1.1+Xcode 6.1+iOS 8.1対応]

iOS7開発者向けお勧め本紹介を以前に紹介させていただきまいたが、今回

Swift入門(Xcode6のXCTestフレームワークで学ぶ) 第二回「関数(メソッド)とクロージャーの利用方法」

前回はSwiftの概要をザックリと説明させていただきました。 今

→もっと見る

Optimization WordPress Plugins & Solutions by W3 EDGE
PAGE TOP ↑