zoukankan      html  css  js  c++  java
  • iOS-runtime-根据协议名调某一个类有与协议里面放的相同的方法

    //
    //  ViewController.m
    //  ObserverTrampoline
    //
    //  Created by Rob Napier on 9/7/11.
    //  Copyright (c) 2011 __MyCompanyName__. All rights reserved.
    //
    
    #import "ViewController.h"
    #import "RNObserverManager.h"
    
    @protocol MyProtocol <NSObject>
    @optional
    - (void)doSomething;
    
    
    - (void)dodo;
    
    @end
    
    @interface MyClass : NSObject <MyProtocol>
    @end
    
    @implementation MyClass
    
    - (void)doSomething {
      NSLog(@"doSomething :%@", self);
    }
    
    @end
    
    
    @interface MyClass1 : NSObject
    @end
    
    @implementation MyClass1
    
    - (void)dodo1 {
        NSLog(@"dodo1 :%@", self);
    }
    
    - (void)dodo {
        NSLog(@"dodo 要走");
    }
    
    @end
    
    @implementation ViewController
    //@synthesize observerManager=trampoline_;
    
    - (void)viewDidLoad {
      [super viewDidLoad];
        
      //这样就可以执行一些事情,比如一个类遵守某个协议,它可以直接调这个协议执行那个类里面写的something
        
      NSSet *observers = [NSSet setWithObjects:[MyClass new],[MyClass1 new], nil];
    
      self.observerManager = [[RNObserverManager alloc] 
                              initWithProtocol:@protocol(MyProtocol) 
                              observers:observers];
      
      [self.observerManager doSomething];
      [self.observerManager dodo];
    
    }
    
    @end

    实现的方法

    #import "RNObserverManager.h"
    
    @interface RNObserverManager ()
    @property (nonatomic, readonly, strong) NSMutableSet *observers;
    @property (nonatomic, readonly, strong) Protocol *protocol;
    @end
    
    @implementation RNObserverManager
    //协议 集合
    - (id)initWithProtocol:(Protocol *)protocol
                 observers:(NSSet *)observers {
        if ((self = [super init])) {
            _protocol = protocol;
            _observers = [NSMutableSet setWithSet:observers];
        }
        return self;
    }
    
    - (void)addObserver:(id)observer {
      NSAssert([observer conformsToProtocol:self.protocol], 
               @"Observer must conform to protocol.");
        [self.observers addObject:observer];
    }
    
    - (void)removeObserver:(id)observer {
        [self.observers removeObject:observer];
    }
    
    
    //NSObject --------
    //这个函数让重载方有机会抛出一个函数的签名,再由后面的forwardInvocation:去执行。
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
        NSMethodSignature *
      result = [super methodSignatureForSelector:sel];
      if (result) {
       return result; 
      }
      
      // Look for a required method
        struct objc_method_description desc = 
                 protocol_getMethodDescription(self.protocol,
                                               sel, YES, YES);
        if (desc.name == NULL) {
            // Couldn't find it. Maybe it's optional
            desc = protocol_getMethodDescription(self.protocol,
                                             sel, NO, YES);
        }
      
        if (desc.name == NULL) {
        // Couldn't find it. Raise NSInvalidArgumentException
            [self doesNotRecognizeSelector:sel];
            return nil;
      }
      
      return [NSMethodSignature signatureWithObjCTypes:desc.types];
    }
    
    //真正执行从methodSignatureForSelector:返回的NSMethodSignature。在这个函数里可以将NSInvocation多次转发到多个对象中,这也是这种方式灵活的地方。(forwardingTargetForSelector只能以Selector的形式转向一个对象)
    
    - (void)forwardInvocation:(NSInvocation *)invocation {
        SEL selector = [invocation selector];
        for (id responder in self.observers) {
            if ([responder respondsToSelector:selector]) {
                [invocation setTarget:responder];
                [invocation invoke];
            }
        }
    }

    参考:http://www.cnblogs.com/biosli/p/NSObject_inherit_2.html

    http://blog.csdn.net/yiyaaixuexi/article/details/8970734

  • 相关阅读:
    react的CSS中 :global的含义
    TypeScript中的问号 ? 与感叹号 ! 的含义
    移动端1px问题的解决方案
    原生js实现call,apply以及bind
    哪些场景不能使用箭头函数
    线性渐变、径向渐变以及圆锥渐变
    vue 开发中实现provide和inject实现依赖注入
    inline-block元素去除间隙
    clientWidth、offsetWidth、scrollWidth的区别
    session、token和cookie
  • 原文地址:https://www.cnblogs.com/hxwj/p/4795637.html
Copyright © 2011-2022 走看看