• 15
    Like
  • 0
    Comment

スマートテック・ベンチャーズ最終日担当の@ktaguchiです。
今回のテーマはdelegateです。

きっかけは後輩に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クラス以外にも様々なクラスから使われるとしてもそのクラスのことを知らなくていいのです。
これは各クラスが複雑に依存しあうカオスな状況を避けられることを意味します。

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

最後に

スマートテック・ベンチャーズでは、未経験だけどiOSの開発をやりたい!という人を募集しています。
Advent Calendarのスマートテック・ベンチャーズページに会社およびWantedlyのURLを載せていますので、興味のある方は是非ご覧ください。
http://qiita.com/advent-calendar/2016/stv

本投稿がスマートテック・ベンチャーズ Advent Calendar 2016のラストです。
最後までお付き合いいただき、ありがとうございました!

いや付き合ってねーよ。たまたまこの記事見ただけだよ。という方もご覧いただきありがとうございます。
よろしければ他の記事もご覧いただけるとSTV一同泣いて喜びます・・・(笑)

2017年もこれまで以上に頑張りますので、スマートテック・ベンチャーズをよろしくお願いいたします!