iOS | NSProxy

Objective-C作为一种动态消息型语言,其机制不同于Java ,C#等编译型语言.
它将数据类型的确定等工作推迟到了运行时期来执行,并且它调用方法的方式实质是像对象发送消息,根据selector在对象的本类以及父类中的方法列表进行查找,如果都找不到就会启动消息转发机制.

回到正题,这个话题我想谈下OC的单继承原则.
OC确实是只能单继承的语言,但是基于运行时的机制,却有一种方法让它来实现一下"伪多继承".就是利用NSProxy这个类.

NSProxy是和NSObject同级的一个类,可以说它是一个虚拟类,它只是实现了<NSObject>的协议.它的作用有点类似于一个复制类,有人曾经笑谈它是卡卡西的复制忍术,想想其实也挺贴切的,其实原理确实如此.

过程:
用一个继承于NSProxy的子类,在它内部实现一些方法,暴露一个公开方法transform,这个方法是使它变身的关键.然后它变身之后可以对那些对象发送消息,并且可以在内部拦截消息的内容并修改.

可以说,几乎可以变身成为任何对象.

直接上个代码来展示下

JanProxy.h

#import <Foundation/Foundation.h>

@interface JanProxy : NSProxy

- (void)transformObjc:(NSObject *)objc;

@end

JanProxy.m

#import "JanProxy.h"

@interface JanProxy ()

@property(nonatomic,strong)NSObject *objc;

@end

@implementation JanProxy



- (void)transformObjc:(NSObject *)objc
{
    //复制对象
    self.objc = objc;
}

//2.有了方法签名之后就会调用方法实现
- (void)forwardInvocation:(NSInvocation *)invocation
{
    if (self.objc) {
        //拦截方法的执行者为复制的对象
        [invocation setTarget:self.objc];
           
        if ([self.objc isKindOfClass:[NSClassFromString(@"Cat") class]]) {
            //拦截参数 Argument:表示的是方法的参数  index:表示的是方法参数的下标
            NSString *str = @"拦截消息";
            [invocation setArgument:&str atIndex:2];
        }
        
        //开始调用方法
        [invocation invoke];
    }
    
}

//1.查询该方法的方法签名
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel
{
    NSMethodSignature *signature = nil;
    if ([self.objc methodSignatureForSelector:sel]) {
        signature = [self.objc methodSignatureForSelector:sel];
    }
    else
    {
        signature = [super methodSignatureForSelector:sel];
    }
    
    return signature;
}

@end

使用方法


     Dog *dog = [[Dog alloc]init];
    
    //OC中方法的调用本质上是给这个对象发送一个消息
    Cat *cat = [[Cat alloc] init];
 
    //开始复制拦截方法
    JanProxy *proxy = [JanProxy alloc];
    //开始变身成猫
    [proxy transformObjc:cat];
    //开始调猫的方法
    [proxy performSelector:@selector(eat:) withObject:@"猫发出消息"];
    
    //开始变身成狗
    [proxy transformObjc:Dog];
    //开始调用学生的方法
    [proxy performSelector:@selector(shut)];

最后的结果

控制台输出结果

发现没有,猫发出消息已经被子类的内部拦截并且做出了修改.

总结

OC中存在这么一个默默无闻的类NSProxy,填补了"多继承"这个空白区.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 5,826评论 0 9
  • 转自:使用NSProxy和NSObject设计代理类的差异 经常发现在一些需要使用消息转发而创建代理类时, 不同的...
    iOS_肖晨阅读 7,584评论 0 54
  • 目录 Objective-C Runtime到底是什么 Objective-C的元素认知 Runtime详解 应用...
    Ryan___阅读 5,919评论 1 3
  • 1.理解NSObject和元类 1.1 在OC中的对象和类是什么 对象是在objc.h中定义的 类是在runtim...
    HWenj阅读 4,427评论 0 3
  • NSProxy类在分布式对象架构中是很重要的。由于作用比较特别,NSProxy在Cocoa程序中出现频率很低。 N...
    iOS_肖晨阅读 5,040评论 0 51