[Objective-C] デリゲート (Delegate)を理解する!

公開日: : 最終更新日:2014/08/19 iPhone App 開発, Objective-C ,

デリゲートとは?

デリゲートに関しての意味合いとして、”委譲”とか”代理”と説明されることが多いです。
簡単にいえば、”自分ができないことや、自分がやってほしいことを相手に頼む” ことです。

たとえば、2つの画面(ViewController)があるとします。
相手の画面から自分の画面が呼ばれました。
そしてアレコレ処理をして自分の画面が閉じられたときに、相手の画面にアラートを表示させるとか、自分の情報を保存してほしいときなどです。
自分の画面は閉じられてしまうので、自分では処理できない。それを他人にやってもらうわけです。

自分「もう眠いし寝ようかな。」
相手「いいよ。早く寝なよ。」
自分「自分はもうすぐ寝るけど寝たらやってほしいことあるんだけど...」
相手「なに?」
自分「紙にメモっといた。」←デリゲートの宣言
相手「わかったよ。あんたが寝たらやっておくよ。」
自分「頼んだ。」

自分「zzz...」
相手「じゃあやるか。」←デリゲートの実行

ざっくりとストーリー仕立てにしてみました。(クオリティ低すぎる。。。)

では実装してみます!

わからない場合は、[Objective-C] UINavigationControllerのセグエを使って画面遷移をする を参考にしてください。

  • 2つの画面(ViewController)を用意します。
  • AiteViewController(相手の画面)
  • JibunViewController(自分の画面)
  • AiteViewControllerにNavigationControllerをEmbed inします。
  • JibunViewControllerにNavigationControllerをEmbed inします。
  • AiteViewControllerにButton(自分に遷移)を追加します。
  • そのButtonからJibunViewController側のNavigationControllerにセグエを紐づけます。このときPushではなくModelにしてください。

スクリーンショット 2014-08-08 12.01.23

  • JibunViewControllerにButton(閉じる)を追加します。
  • JibunViewControllerのButtonをヘッダーファイルに結びつけてボタンアクションを追加します。

Storyboardはこんな感じになりました。

スクリーンショット 2014-08-08 12.42.17

処理の流れは...

  • 相手の画面から自分の画面に遷移する
  • 自分の画面が閉じられる(寝る)
  • 相手の画面でログを出力する(メモをみて頼まれたことをやる)

デリゲート

ではこの場合、メモにあたるデリゲートを作成していきます。
メニューの「File > New > File…」からファイルを選択します。
テンプレートは「Objective-C protocol」を選択、ファイル名はMemoDelegateとします。
そして以下のように編集します。

#import <Foundation/Foundation.h>

@protocol MemoDelegate <NSObject>

- (void)buyTabako;
- (void)washing;

@end

メモに書いてあったのは「タバコを買いに行く」と「洗濯をする」です!
自分が寝たらこの2つを相手に実行させるのです!

頼む側:JibunViewController

ではJibunViewControllerの実装です。

JibunViewController.h(ヘッダーファイル)は以下の通りです。

#import <UIKit/UIKit.h>
#import "MemoDelegate.h"

@interface JibunViewController : UIViewController

@property (weak, nonatomic) id <MemoDelegate> delegate;

- (IBAction)buttonClosed:(id)sender;

@end

自分がメモを作ったのですから、デリゲートをプロパティとして宣言します。
buttonClosedはボタンが押されたときのイベントになります。

次はJibunViewController.m(実装ファイル)のボタンイベントを以下の通りに編集します。

- (IBAction)buttonClosed:(id)sender
{
    [self dismissViewControllerAnimated:TRUE completion:nil];

    [self.delegate buyTabako];
    [self.delegate washing];
}

ボタンを押されると自分は寝ます。
dismissViewControllerAnimatedで自分の画面が閉じられます。
そして相手にやってほしいことのメモ内容を書いときます。

頼まれる側:AiteViewController

次にAiteViewController.h(ヘッダーファイル)です。

#import <UIKit/UIKit.h>
#import "MemoDelegate.h"

@interface AiteViewController : UIViewController<MemoDelegate>

@end

相手はこのメモを頼まれてるよーとカギかっこで宣言します。

そしてAiteViewController.m(実装ファイル)を編集します。
デリゲートを宣言した時点で、頼まれたことを書いてないよーと警告されているのがわかります。

スクリーンショット 2014-08-08 13.43.47

なので頼まれごとを書いときます。以下のコード追加してください。

- (void)buyTabako
{
    NSLog(@"%@", @"たばこ買いに行くよ!");
}

- (void)washPants
{
    NSLog(@"%@", @"洗濯するよ!");
}

 

NSLogでコンソールにメッセージを出力します。

そして、これが重要!
頼まれた人は頼んだ人のdelegateにself(頼まれた人自身)を設定してやります。以下のコードを追加してください。

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"showJibun"])
    {
        UINavigationController *navigationController = segue.destinationViewController;
        JibunViewController *jibunViewController = [navigationController viewControllers][0];
        jibunViewController.delegate = self;
    }
}

prepareForSegueは画面遷移する前にする処理です。

segue.destinationViewControllerで遷移先の画面を取得します。
遷移先はNavigationControllerなので、その中に入っているJibunViewControllerを取得します。
[navigationController viewControllers]でナビゲーションで格納された画面(配列)が取得できます。その最初のViewControllerを配列の最初で指定して取得しています。
そしてself(自身)を設定します。

あとは、インポートするのを忘れずに。

#import "JibunViewController.h"

以上で、出来あがりです。さっそく実行してみましょう!

実行結果

スクリーンショット 2014-08-08 16.24.11

まとめ

デリゲートは難しいですね。

今回の例に限らず、デリゲートというよりもイベントと解釈したほうがよいのかもしれません。「ボタンを押す→そのときに別のオブジェクトで特定の処理をする」みたいな感じですかね。
この記事を参考に、皆さんもぜひデリゲートを試してみてください!

ad

関連記事

[iPhone App] WorkManagerの不具合について

バージョン1.2.2の不具合 11/25日現在、iPhoneアプリの「WorkManger」バージ

記事を読む

[Swift] CoreDataを使ってみる

SwiftでCoreData 今回はSwiftでCoreDataを使ってみます。 Xcodeプロ

記事を読む

no image

爆走中!

挫折街道爆走中です! が! 迷走中でもあるわけです、はい。 そんな中で、迷走するに至った訳

記事を読む

no image

一旦、離脱中!

サイト制作の仕事がちょろちょろちょろっと入ってきたので、寂しいけれどしばしXcodeとはお別れ。

記事を読む

[Objective-C] 共通関数をまとめたクラスを作ろう!

共通クラスとは? アプリを作っていると「この処理何回も書いてるなー」ということが多々あると思います

記事を読む

[iPhone App]WorkManager アップデートしました。

Processing For App Storeでやきもきした僕です。こんにちわ。 今

記事を読む

[Swift] CoreDataのテーブルからデータ件数を取得する

件数を取得する fetchResultsControllerなどを使わず、直接テーブルのデータ件数

記事を読む

[Swift] optional値の設定(??)

optional値がnilの時 プロジェクトでのテンプレートを選択した時にソースコードが自動生成さ

記事を読む

TabBarControllerとNavigationControllerのボタン追加

TabBarとNavigationを同時に使っているViewControllerの場合、naviga

記事を読む

[Objective-C] 文字列操作の便利Tips

Tipsいろいろ 先日の投稿 共通関数をまとめたクラスを作ろう!の流れで、文字列を操作するときに便

記事を読む

ad

Message

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

ad

[PHP] curl転送してみる(googleに)

curlでgoogle画像検索APIにアクセスしてみます。 cu

[PHP] PDOでMySQLの接続確認をする

PDO PHPでMySQLに接続する際には、mysql_connec

[PHP] ランダムな英数字を生成する

便利系メソッド 今回はPHPでランダムな英数字を作成してみます。

[Swift] プロパティリスト(plist)の値を取得

plistからデータを取得してみます。 こちらのエントリーも参考にし

[Swift] Asset Catalogについて

XCode5から追加されたAsset Catalog。 いままで標準

→もっと見る

  • 1978年の七夕生まれ。 25才でweb業界の門を叩き、28才でフリーランスに。 現在は、フリーランスでマークアップ中心に、wordpressのカスタマイズやデザインをしております。 また、iPhoneアプリの開発もしております。
PAGE TOP ↑