您的位置:首页 > 移动开发 > IOS开发

iOS-runtime-根据协议名调某一个类有与协议里面放的相同的方法

2015-09-09 18:37 316 查看
//
//  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

/article/1608544.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: