LoginSignup
5
6

More than 3 years have passed since last update.

【デザインパターン】複数にデリゲートする方法 Multicast Delegate Pattern

Last updated at Posted at 2016-06-28

Multicast Delegate Pattern

delegateは処理の一部を委譲するときに使うものです。
この通知先を複数にする方法を紹介します。

使用例

MultiDelegateProxy *delegateProxy = [[MultiDelegateProxy alloc] initWithTarget:self, nil];
[delegateProxy addTarget:xxx];
[delegateProxy addTarget:zzz];
self.scrollView.delegate = (id)delegateProxy;

実装例

MultiDelegateProxy.h
#import <Foundation/Foundation.h>

@interface MultiDelegateProxy : NSProxy
- (instancetype)initWithTarget:(NSObject *)targets, ... NS_REQUIRES_NIL_TERMINATION;
- (void)addTarget:(NSObject *)target;
- (void)removeTarget:(NSObject *)target;
@end

MultiDelegateProxy.m
#import "MultiDelegateProxy.h"

@interface MultiDelegateProxy ()
@property (strong, nonatomic) NSMutableArray* targets;
@end

@implementation MultiDelegateProxy

- (instancetype)initWithTarget:(NSObject *)targets, ... {
    _targets = @[].mutableCopy;
    va_list arguments;
    va_start(arguments, targets);
    NSObject *value = targets;
    while (value) {
        [_targets addObject:value];
        value = va_arg(arguments, typeof(NSObject*));
    }
    va_end(arguments);
    return _targets.count ? self : nil;
}

- (void)forwardInvocation:(NSInvocation *)invocation {
    for(NSObject *target in _targets.copy) {
        if ([target respondsToSelector:invocation.selector]) {
            [invocation invokeWithTarget:target];
        }
    }
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
    for(NSObject *target in _targets.copy) {
        if ([target respondsToSelector:sel]) {
            return [target methodSignatureForSelector:sel];
        }
    }
    return nil;
}

- (BOOL)respondsToSelector:(SEL)aSelector {

    if ([super respondsToSelector:aSelector]) {
        return YES;
    }

    for(NSObject *target in _targets.copy) {
        if ([target respondsToSelector:aSelector]) {
            return YES;
        }
    }
    return NO;
}

- (BOOL)conformsToProtocol:(Protocol *)aProtocol {
    for(NSObject *target in _targets.copy) {
        if ([target conformsToProtocol:aProtocol]) {
            return YES;
        }
    }
    return NO;
}

- (void)addTarget:(NSObject *)target {
    if (target && ![_targets containsObject:target]) {
        [_targets addObject:target];
    }
}

- (void)removeTarget:(NSObject *)target {
    if (target && [_targets containsObject:target]) {
        [_targets removeObject:target];
    }
}

@end

参考リンク

Article

http://blog.fenrir-inc.com/jp/2013/11/nsproxy.html
http://blog.scottlogic.com/2012/11/19/a-multicast-delegate-pattern-for-ios-controls.html
http://www.gregread.com/2016/02/23/multicast-delegates-in-swift/

OSS

https://github.com/tumtumtum/SwiftMulticastDelegate
https://github.com/jonasman/MulticastDelegate

Original

5
6
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
5
6