提到了resolveInstanceMethod,这个方法不仅在这里用,还用来实现消息的转发。

消息的转发就是向对象发送一个它本身并没有实现的消息,在运行时确定它实际产生的行为。

举个例子来说,一个Person对象,在运行时根据实际情况,决定是否响应fly这样的方法。如果条件具备,则fly被响应。否则,则不具备这样的方法。类似于AoP的做法。

要实现消息转发,需要覆盖三个方法:

1, resolveInstanceMethod(可选),这个方法为你提供了一个机会,在消息被发现本身没有在类中定义时你可以通过class_addMethod将它添加进去。如果你不这样做,不管你最终返回YES还是NO,程序都会jmp到下一个方法。

2, –(NSMethodSignature*)methodSignatureForSelector: (SEL) sel;通过覆盖这个方法,可以将你要转发的消息的签名创建并返回。如果在这里你返回nil,那么就会直接抛出异常。如果返回一个签名,则程序会jmp到第三个方法。这里返回的方法签名,必须满足两个条件之一(方法名相同||输入参数相同).

3, –(void)forwardInvocation:(NSInvocation * )anInvocation;在这里进行实际的方法调用。

#import <Foundation/Foundation.h>

#import "Human.h"

@interface Plane : NSObject

-(void)fly:(Human*)p;

-(int)fly1;

-(void)fly2:(Human*)p withBird:(NSString*)birdName;

@end

#import "Plane.h"

@implementation Plane

-(void)fly:(Human*)p{

NSLog(@"Fly with a guy whose information is \"%@\"", [p description]);

NSLog(@"fly......");

}

-(int)fly1{

NSLog(@"I can fly in Plane for fly1");

return 0;

}

-(void)fly2:(Human*)p withBird:(NSString*)birdName{

NSLog(@"Fly with a guy whose information is \"%@\"", [p description]);

NSLog(@"fly......bird:'%@'.", birdName);

}

@end

#import <Foundation/Foundation.h>

void dynamicMethod(id self, SEL _cmd, float height);

@interface Human : NSObject{

float _height;

}

@property(retain, nonatomic) NSString * name;

@property(readonly) float weight;

@property float height;

-(id) initWithWeight:(float)weight;

-(NSString*)description;

@end

#import <objc/runtime.h>

#import "Human.h"

#import "Plane.h"

void dynamicMethod(id self, SEL _cmd, float height){

NSLog(@"dynamicMethod:%@", NSStringFromSelector(_cmd));

// here is a question. how to implement the statements to assign the property of id(human.height);

// looks like the dynamic property is just for linkage.

// 当赋值发生时,由于动态函数的全局性,可以访问其他全局变量,对象。所以更像一种链接机制

}

@implementation Human

@synthesize name;

@synthesize weight;

@dynamic height;

-(id)initWithWeight:(float)w{

if(self=[super init]){

weight = w;

}

return self;

}

-(NSString*)description{

return [NSString stringWithFormat:@"The human whose name is \"%@\". weight is [%f]. height is [%f]",

self.name, self.weight, self.height];

}

-(float)height{

return _height;

}

-(void)fly2{

NSLog(@"yes I can fly in 2!");

}

+(BOOL)resolveInstanceMethod:(SEL)sel{

NSString* method = NSStringFromSelector(sel);

if([method isEqualToString:@"setHeight:"]){

class_addMethod([self class], sel, (IMP)dynamicMethod, "v@:f");

}

return [super resolveInstanceMethod:sel];

}

-(NSMethodSignature*)methodSignatureForSelector:(SEL)selector{

NSMethodSignature * signature = [super methodSignatureForSelector:selector];

if(!signature&&[NSStringFromSelector(selector) isEqualToString:@"fly"]){

//signature = [[self class] instanceMethodSignatureForSelector:@selector(fly2)];

SEL newSel = NSSelectorFromString(@"fly1"); //will ok.

// SEL newSel = NSSelectorFromString(@"fly:");//will ok.

// SEL newSel = NSSelectorFromString(@"fly2:withBird");//will wrong.

//这里返回的消息,必须符合以下条件之一:

//方法名相同

//输入参数相同

if([Plane instancesRespondToSelector:newSel]){

signature = [Plane instanceMethodSignatureForSelector:newSel];

}

}

return signature;

}

-(void)forwardInvocation:(NSInvocation *)anInvocation{

NSString * selName = NSStringFromSelector([anInvocation selector]);

NSMethodSignature * sig = [anInvocation methodSignature];

NSLog(@"the signature %@", [NSString stringWithCString:[sig methodReturnType] encoding:NSUTF8StringEncoding]);

if([selName isEqualToString:@"fly"]){

Plane * p = [[Plane alloc] init];

SEL newSel = NSSelectorFromString(@"fly:");

IMP imp = [p methodForSelector:newSel];

imp(p, newSel, self);

[p release];

}

}

-(void)dealloc{

[self setName:nil];

[super dealloc];

}

@end

#import <Foundation/Foundation.h>

#import <objc/runtime.h>

#import "Human.h"

#import "Plane.h"

int main (int argc, const char * argv[])

{

@autoreleasepool {

// insert code here...

Human * h = [[Human alloc] initWithWeight:17.3];

h.name=@"Chris";

h.height = 18.0;

NSLog(@"%@", [h description]);

[h fly];

[h release];

h=nil;

转载于:https://www.cnblogs.com/DamonTang/archive/2012/11/08/2760360.html

Objective-C 2.0的运行时编程-消息转发相关推荐

  1. Swift和Objective-C的运行时编程

    \ 本文要点 \\ 运行时编程是Objective-C编程人员的重要工具,它提供了一些系统框架的基础.\\t 尽管运行时编程的确移除了不少的样板文本(Boilerplate),使开发人员可以编写更为精 ...

  2. 聊一聊Android 6.0的运行时权限

    Android 6.0,代号棉花糖,自发布伊始,其主要的特征运行时权限就很受关注.因为这一特征不仅改善了用户对于应用的使用体验,还使得应用开发者在实践开发中需要做出改变. 没有深入了解运行时权限的开发 ...

  3. 如何正确处理Android6.0+的运行时权限申请

    从 Android 6.0(API 23) 开始,允许用户在应用运行时向其授予权限,好处有: 简化应用安装过程,无需在安装或更新时授予权限 用户可以对应用的功能进行更多控制:例如,用户可以选择为相机应 ...

  4. 安卓从业者应该关注:Android 6.0的运行时权限

    Android 6.0,代号棉花糖,自发布伊始,其主要的特征运行时权限就很受关注.因为这一特征不仅改善了用户对于应用的使用体验,还使得应用开发者在实践开发中需要做出改变. 没有深入了解运行时权限的开发 ...

  5. runtime运行时编程一些相关知识

    http://blog.csdn.net/lizhongfu2013/article/details/9497721 转载于:https://blog.51cto.com/8287272/167276 ...

  6. 混合模式程序集是针对“v2.0.50727”版的运行时生成的,在没有配置其他信息的情况下,无法在 4.0 运行时中加载该程序集...

    其调用的方法是从sqlite数据库中获取原来已经使用过的数据库连接,当时也没注意,就是准备设断点然后单步调试,结果竟然是断点无法进入方法体内,后来仔细看了一下方法体的时候发现了一个问题,就是现有的Sy ...

  7. Android6.0运行时权限处理

    前言 在Android6.0版本以前,往往是应用程序需要什么权限直接在manifest.xml中直接声明,当你安装程序的时候,如果不想让该程序使用某种权限,唯一的办法只能是不装这个应用,但是我们生活中 ...

  8. C++知识点54——RTTI(运行时类型识别)

    一.RTTI概述 RTTI的功能由两个运算符实现,一个是typeid,用来返回表达式的类型:另一个是dynamic_cast,作用是将基类的指针或引用安全地转为子类的指针或引用 二.typeid ty ...

  9. java运行安全_Java运行时环境

    不知道如何下载?点击我 Java是一个通用术语,用于指代Java软件及其组件,包括" Java运行时环境(JRE)"和" Java虚拟机(JVM)". JAVA ...

最新文章

  1. 计算机图画大赛作品六年级,小学学生电脑绘画比赛活动方案
  2. python reader循环_python – 多次循环遍历csv.DictReader行
  3. mysql 统计日报_mysql 数据分析如何实现日报、周报、月报和年报?
  4. IDA反编译失败总结
  5. 我所理解的离散傅里叶变换_DFT
  6. 单片机 PWM输出 c
  7. 小记 cin/get/getline
  8. 网友希望一加7像iPhone XR一样流畅 刘作虎:iPhone很卡
  9. linux7怎么禁止用户密码登录,Centos7锁定用户禁止登陆的解决办法
  10. express中间件和路由教程
  11. ubuntu20.04 安装、美化、办公环境搭建及深度学习开发环境搭建
  12. POJ-3744 Scout YYF I 概率DP
  13. 经纬度转化为xy坐标系_Arcgis添加经纬度矢量点
  14. android EditText的美化
  15. 关于Linux系统中文件名中带有空格问题分析
  16. stata实现经济生态的空间杜宾模型
  17. linux下tar.bz2文件的 解压缩方法
  18. 微信小程序电商商城系统怎样搭建?
  19. PL/0语言 词法分析
  20. centOS命令之ln

热门文章

  1. 计算机一级在线练习,计算机一级练习系统
  2. Kotlin基础 — 扩展函数
  3. Nginx+Tomcat部署Angular+javaweb项目(解决刷新404)
  4. 【Python】区分List 和String
  5. Netty解决TCP的粘包和分包(二)
  6. javascript中引号嵌套
  7. 在域中使用组策略允许用户关闭计算机以及更改系统时间
  8. Tomacat7启动报错 org.apache.catalina.deploy.WebXml addFilter
  9. linux oracle hostname,How to Change hostname in Oracle Linux 7
  10. numpy功能快速查找