美文网首页
Objective-C中的复制忍者卡卡

Objective-C中的复制忍者卡卡

作者: 周老实 | 来源:发表于2018-01-05 17:30 被阅读0次

是不是曾经在别人面前夸下海口:Objective-C中所有的类的基类都是NSObject;我之前也一直也这么以为的,但是认真看了下官方文档:

NSObject

啪啪,好响,好疼~(看来英文水平也很重要啊......)
不卖关子了,我们今天要讨论的就是NSProxy。它是跟NSObject属于同一级别的类,是个抽象类,只是实现了<NSObject>的协议;

NSProxy

按照官方的定义:NSProxy是一个为对象定义接口的抽象父类,并且为其它对象或者一些不存在的对象扮演了替身角色。通常,给proxy的消息被转发给实际对象或者导致proxy加载(转化它为)实际对象。NSProxy的子类能被用来实现透明的分布式消息(例如:NSDistantObject)或者延缓要花费昂贵代价创建的对象的实现。

下面我们看看NSProxy是怎么复制别的类(几乎所有类)的:

我们先创建一个类继承自NSProxy:

#import "KakashiProxy.h"

@interface KakashiProxy ()

@property(nonatomic,strong)NSObject *objc;

@end

@implementation KakashiProxy

- (void)changeObj:(NSObject *)obj {
    
    self.objc = obj;
    
}

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

//调用方法实现
- (void)forwardInvocation:(NSInvocation *)invocation {
    
    if ([self.objc respondsToSelector:invocation.selector]) {
        NSString *selName = NSStringFromSelector(invocation.selector);
        NSLog(@"selector name : %@",selName);
        //这里我们可以做一些逻辑处理,比如埋点统计之类的
        [invocation invokeWithTarget:self.objc];
    }else {
        [super forwardInvocation:invocation];
    }
    
}

@end

可以看到我们重写了两个方法:methodSignatureForSelector:forwardInvocation:(NSInvocation *)invocation,前者是实现方法签名的,我们可以在这个方法中,直接将我们复制的对象进行方法签名,然后生成NSInvocation。接着方法forwardInvocation会被调用,在这个方法中,我们直接将invacationtarget设置为我们复制的对象。在这个方法中我们可以做一点事情,比如根据类名做一些逻辑,也可以做一些数据埋点之类的。
然后我们看看怎么使用这个复制忍者的:
我们随便定义两个类,并为每个类设置了一个方法:

Parker-Dog.h

    #import "Parker-Dog.h"
    
    @implementation Parker_Dog
    
    - (void)bite {
        NSLog(@"卡卡西召唤通灵兽Paker并咬住了再不斩!");
    }
    
    @end

Wood.h

    #import "Wood.h"

    @implementation Wood
    
    - (void)boom{
    
        NSLog(@"变!木头!...");
        
    }

调用:

    //初始化一个木头
    Wood *wood = [[Wood alloc] init];
    //初始化一个帕克
    Parker_Dog  *paker = [[Parker_Dog alloc] init];
    //初始化一个卡卡西
    KakashiProxy *proxy = [KakashiProxy alloc];
    
    //变木头
    [proxy changeObj:wood];
    //调用木头的方法
    [proxy performSelector:@selector(boom) withObject:nil];
    
    //变帕克
    [proxy changeObj:paker];
    //调用帕克的方法
    [proxy performSelector:@selector(bite) withObject:nil];

控制台输出:


控制台输出

这样,我们通过proxy这个类实现了复制woodpaker,可以分别调用各个类的方法了。

总结

其实也不能叫复制吧,大家也可以看到,这个实现其实就是利用了runtime的消息转发机制。这篇文章就算是对NSProxy的一个简单认识吧,还有些NSProxy的高级用法可能笔者还没有学习到,还要继续努力,有时间需要深入研究下这个特殊的类。

参看文章

相关文章

  • Objective-C中的复制忍者卡卡

    是不是曾经在别人面前夸下海口:Objective-C中所有的类的基类都是NSObject;我之前也一直也这么以为的...

  • 火影忍者:漫画中期以后,写轮眼的复制功能为什么没人用了

    卡卡西被以拷贝忍者之名让敌国忍者闻风丧胆,在波之国队长再不斩的时候,卡卡西是写轮眼的解析忍术的能力复制出再不斩的忍...

  • copy忍者旗木卡卡西

    看过《火影忍者》的应该知道鸣人的老师——旗木卡卡西,他被称作copy 忍者,是因为他可以用自己特殊的写轮眼,复制对...

  • 旗木卡卡西

    如果说奈良鹿丸是火影忍者里唯一可以嫁的人,那么卡卡西就我是唯一想嫁的人。 卡卡西5岁从忍者学校毕业,6岁升为中忍,...

  • 卡卡西实战表现怎么样?具体打法是什么?

    卡卡西实战表现怎么样?具体打法是什么? 火影忍者手游旗木卡卡西实战表现怎么样?具体打法是什么?在日本动漫《火影忍者...

  • 初识卡卡西再到了解

    刚开始追火影忍者,只觉得卡卡西十一个帅气,厉害,又很幽默的忍者。 随着剧情的发展,渐渐了解了他是忍者口中的...

  • NinjaPuzzle

    【游戏介绍】 新一代热血超燃日系忍者卡牌《忍者别嚣张》,是颇受好评卡牌手游《鬼影忍者》的最新力作,由原开发团队精心...

  • 王潇晨颁奖词

    我为王晓晨颁得奖是旗木卡卡西奖,在《火影忍者》中,卡卡西是一个冷静,拥有高超的头脑,同时也很爱看书,但是不爱说话,...

  • 《火影忍者》天才忍者卡卡西,为什么成了55开?

    卡卡西在《火影忍者》初期绝对是人气王,帅气的造型加上完美的战绩,很多人要比主角还喜欢卡卡西。 可是,在看完《火影忍...

  • 解KI

    破解SIM卡(移动、联通)KI的方法 破解KI的目的是为了复制SIM卡,而复制SIM卡是为了达到“多机一号...

网友评论

      本文标题:Objective-C中的复制忍者卡卡

      本文链接:https://www.haomeiwen.com/subject/ozusnxtx.html