きっかけは後輩にdelegateについて教える機会があったことです。

最初は自分もなかなか理解できなかったことを思い出しました。

delegateを理解する手助けができるような記事になればと思っています。


こんな人にオススメ


  • ViewControllerに処理を書いていけばiOSアプリ作れる人

  • でも処理を他のクラスに切り出すのは難しい、という人

  • なんとなくdelegateって言葉は知っているけど、自作delegateは作れない・・・という人


書くこと


  • delegateの概要

  • delegateの実装方法


環境


  • Xcode8.2

  • Objective-C


delegateの概要

そもそもdelegateって何なのでしょう。

Appleのドキュメントには下記のように書かれています。

Objective-C プログラミングの概念 p.22)


デリゲート(delegate, 委譲)とは、あるオブジェクトがプログラム中でイベントに遭遇したとき、それに代わって、または連携して処理するオブジェクトのことです。


delegateのイメージ

delegate.001.jpeg

上記の「delegateされる側」というのがdelegateオブジェクトです。

「delegateする側」はdelegateオブジェクトが何者なのかはわからないけど、delegateオブジェクトに対してdelegationの通知を送ります。

そして、delegateオブジェクトは通知を受け取ったあとの処理を行います。


delegateの実装方法

それではdelegateはどのようにコードにすればいいのでしょうか。

だらだら説明するより実際に見たほうが早いと思うので、簡単なサンプルコードを書いてみました。

補足をコメントに記載しているので参考になれば幸いです。


delegateする側


Hoge.h

#import <Foundation/Foundation.h>


/**
HogeDelegate protocol
*/

@protocol HogeDelegate <NSObject>
/*
@optionalではないメソッドは、delegate準拠先で必ず実装する必要があります。
実装しないと警告が発生します。
*/

@optional
// @optional以下のメソッドはdelegate準拠先での実装は必須ではなくなります。
- (void)didFuga: (NSString *)string;

@end

@interface Hoge : NSObject

/**
delegateオブジェクト
*/

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

- (void)fuga;

@end



Hoge.m

#import "Hoge.h"


@interface Hoge ()

@property (strong, nonatomic) NSString *hogeString;

@end

@implementation Hoge

/*
その他の実装は省略
hogeStringに値が設定されていたりします。
*/

- (void)fuga
{
/*
delegateメソッドが@optionalなので、respondsToSelectorで
delegateオブジェクトがdelegateメソッドを実装しているか判定します。
*/

if ([self.delegate respondsToSelector:@selector(didFuga:)]) {
/*
delegationの通知を送ります。
必要であれば、このように引数にHogeクラス側の情報を渡すことも可能です。
*/

[self.delegate didFuga:self.hogeString];
}
}

@end



delegateされる側


ViewController.m

#import "ViewController.h"

#import "Hoge.h"

@interface ViewController () <HogeDelegate> // HogeDelegateに準拠します

@property (weak, nonatomic) IBOutlet UILabel *hogeLabel;
@property (strong, nonatomic) Hoge *hoge;

@end

@implementation ViewController

#pragma mark - Lifecycle

- (void)viewDidLoad
{
[super viewDidLoad];

self.hoge = [Hoge new];
// hogeのdelegateに自身を指定します。
self.hoge.delegate = self;
[self.hoge fuga];
}

#pragma mark - HogeDelegateMethod

/**
delegationの通知を受けとったら実行する処理
delegateメソッドの具体的な実装を記述します。

@param string Hogeクラス側から渡されてくる文字列
*/
- (void)didFuga:(NSString *)string
{
// Hogeクラス側から渡されてくる文字列をラベルに表示します。
self.hogeLabel.text = string;
}

@end


以上、簡単ではありますがdelegateについて紹介しました。


ポイント1

他クラスに処理してほしいとか、自クラスの値渡したい、というときに便利だと思います。

また、ViewControllerのこの処理のまとまりを別クラスに切り出したい、というときにも役立つはずです。

ViewControllerでやらなければならない処理はdelegateで実装して、その他ロジック等は別クラスとして切り出す、ということができます。


ポイント2

サンプルコードのHogeクラスはViewControllerクラスのことを知りません。

#import "ViewController.h"とか見当たらないですよね)

HogeクラスがViewControllerクラス以外にも様々なクラスから使われるとしてもそのクラスのことを知らなくていいのです。

これは各クラスが複雑に依存しあうカオスな状況を避けられることを意味します。

うまく使って継続開発しやすいアプリを作っていただければと思います!