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
iOS-runtime-根据协议名调某一个类有与协议里面放的相同的方法的更多相关文章
- 22.编写一个类A,该类创建的对象可以调用方法showA输出小写的英文字母表。然后再编写一个A类的子类B,子类B创建的对象不仅可以调用方法showA输出小写的英文字母表,而且可以调用子类新增的方法showB输出大写的英文字母表。最后编写主类C,在主类的main方法 中测试类A与类B。
22.编写一个类A,该类创建的对象可以调用方法showA输出小写的英文字母表.然后再编写一个A类的子类B,子类B创建的对象不仅可以调用方法showA输出小写的英文字母表,而且可以调用子类新增的方法sh ...
- Java基础-接口.编写2个接口:InterfaceA和InterfaceB;在接口InterfaceA中有个方法void printCapitalLetter();在接口InterfaceB中有个方法void printLowercaseLetter();然 后写一个类Print实现接口InterfaceA和InterfaceB,要求 方法 实现输出大写英文字母表的功能,printLowerca
#34.编写2个接口:InterfaceA和InterfaceB:在接口InterfaceA中有个方法void printCapitalLetter():在接口InterfaceB中有个方法void ...
- 常见iOS面试题 之 怎么判断一个类是否遵循某个协议
答案: 使用方法conformsToProtocol. 调用例子: BOOL isConform = [Student conformsToProtocol:@protocol(UIScrollVie ...
- JVM如何加载一个类的过程,双亲委派模型中有哪些方法
1.类加载过程:加载.验证.准备.解析.初始化 加载 在加载阶段,虚拟机主要完成三件事: 1.通过一个类的全限定名来获取定义此类的二进制字节流. 2.将这个字节流所代表的静态存储结构转化为方法 ...
- 13.首先,编写一个类ChongZai,该类中有3个重载的方法void print();其次, 再编写一个主类来测试ChongZai类的功能。
package java1; //计算器 public class Jisuanqi { //属性 //型号,品牌等 //重载 //1.方法同名不同参 //2.返回类型和重载无关 //3.多态的一种表 ...
- 首先,编写一个类ChongZai,该类中有3个重载的方法void print();其次, 再编写一个主类来测试ChongZai类的功能
//计算器 jisuanqi jsq=new jisuanqi(); System., )); System., , )); System.out.println("2.3和4.5 中最大的 ...
- 编写一个类A,该类创建的对象可以调用方法f输出小写的英文字母表。然 后再编写一个A类的子类B,要求子类B必须继承类A的方法f(不允许重写), 子类B创建的对象不仅可以调用方法f输出小写的英文字母表,而且可以调用子 类新增的方法g输出大写的英文字母表。最后编写主类C,在主类的main方法 中测试类A与类B。
package zimu; public class A { public void f() { for (int i = 97; i <123; i++) { System.out.print ...
- iOS runtime 初步学习
注: 在Xocde5之后, 使用运行时方法需要进行2步设置1. 在Build Setting中搜索'msg', 设置'Strict Checking' 为 NO2. 使用需要导入头文件 #import ...
- java一个类 继承HttpServlet 和实现Servlet区别
java一个类 继承HttpServlet 和实现Servlet区别 servlet 是一个接口,如果实现这个接口,那么就必须实现接口里面定义的所有方法 而HttpServlet实现了servlet接 ...
随机推荐
- 1、Centos7 python2.7和yum完全卸载及重装
完全重装python和yum 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 1.删除现有Python ...
- APP弱网测试点
- 在使用线程池时应特别注意对ThreadLocal的使用
使用ThreadLocal并且有线程池时要特别注意,ThreadLocal是以线程为key的,而线程池里面的线程是会被重新利用的,所以如果有使用线程池并且使用ThreadLocal来保存状态信息时要特 ...
- dlopen与dlsym用法
dlopen和dlsym是用于打开动态链接库中的函数,将动态链接库中的函数或类导入到本程序中: dlopen函数: 功能:打开一个动态链接库 包含头文件: #include <dlfcn.h&g ...
- codevs 3344 迷宫
时间限制: 1 s 空间限制: 32000 KB 题目等级 : 黄金 Gold 题目描述 Description 小刚在迷宫内,他需要从A点出发,按顺序经过B,C,D……,到达最后一个点,再回到A ...
- 将回车键转换为Tab键
实现效果: 知识运用: KeyEventArgs类的KeyValue属性 public int KeyValue {get;} //获取KeyDown或KeyUp事件的键盘值 SendKeys类的Se ...
- hrbust-1545-基础数据结构——顺序表(2)
http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1545 基础数据结构——顺序表(2) ...
- 安装VC++6.0实验环境
安装VC++6.0步骤:(1)下载一个压缩包进行解压(2)点击打开解压后的文件(3)找到文件里的程序进行安装(4)等待安装完成该程序后可以试着运行一下此程序,在此我们需要了解编写程序的步骤和注意事项. ...
- java后台验证码的生成
前台代码: <tr> <td>验证码</td> <td><input name="checkCode" type=" ...
- [Tkinter 教程] 布局管理 (Pack Place Grid)
原系列地址: Python Tkinter 简介: 本文讲述如何使用 tkinter 的布局管理 (被称作 layout managers 或 geometry managers). tkinter ...