前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >NSProxy 设计消息转发

NSProxy 设计消息转发

作者头像
老沙
发布2019-09-28 13:19:01
8330
发布2019-09-28 13:19:01
举报
文章被收录于专栏:老沙课堂

首先,了解下NSTimer的循环引用

代码语言:javascript
复制
@interface ViewController ()
@property (nonatomic, strong) NSTimer *timer;
@end

@implementation ViewController  
- (void)viewDidLoad {
    [super viewDidLoad];
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1 
			                  													target:self 
                                                selector:@selector(testForTimer)
                                                userInfo:nil
                                                 repeats:YES];
}

- (void)testForTimer {
    NSLog(@"%s",__func__);
}
@end

循环引用:

mage

  • 可能有的人说用__weak 来修饰self 从而达到target指向ViewController是弱引用的效果。
  • 不行! 因为weak 也是把地址赋值给targettarget还是强引用viewController地址。我们用的weak是处理block的循环引用,block中会把__weak修饰的对象 描述为弱引用
关于SRProxy
代码语言:javascript
复制
@interface SRProxy : NSProxy
@property (nonatomic, weak) id target;
+ (instancetype)proxyWithTarget:(id)target;
@end
代码语言:javascript
复制
@implementation SRProxy
+ (instancetype)proxyWithTarget:(id)target {
    SRProxy *proxy = [SRProxy alloc];
    proxy.target = target;
    return proxy;
}

- (id)forwardingTargetForSelector:(SEL)aSelector {
    if (self.target) {
        return self.target;
    }
    return self;
}

-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    return [self.target  methodSignatureForSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation *)invocation {
    [invocation invokeWithTarget:self.target];
}
@end
关于解决方式
代码语言:javascript
复制
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:[SRProxy proxyWithTarget:self] selector:@selector(testForTimer) userInfo:nil repeats:YES];
解释NSProxy
结构
代码语言:javascript
复制
@interface NSProxy <NSObject> {
    Class	isa;
}

NSProxy为基类,和NSObject同级, 专门处理这种代理实现事件。

SRProxy继承于NSProxy 如果继承NSObject 也可以实现功能。

NSProxy 和NSObject比较

继承于NSProxy的类 找实现方法的时候 只会找当前类是否实现 而不找super,如果没找到直接进入消息动态解析,以及消息转发机制。比继承NSObject的类少了找super,从而效率更高。

实验1

如果把SRProxy中的消息转发机制去掉 看一下错误信息

继承NSProxy
继承NSObject

NSProxy没有init方法 只要alloc 既可

实验2

当我们继承于NSProxy 在上述ViewDidLoad 中打印此代码 结果为

代码语言:javascript
复制
 NSLog(@"isKindOfClass  == %d",[[SRProxy proxyWithTarget:self] isKindOfClass:[self class]]);
解释

调用isKindOfClass 进行消息转发 走的是下面的方法

代码语言:javascript
复制
-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    return [self.target  methodSignatureForSelector:aSelector];
}
代码语言:javascript
复制
- (void)forwardInvocation:(NSInvocation *)invocation {
	[invocation invokeWithTarget:self.target];
}

实际调用的是self.target 去执行objc_msgSend(self.target,SEL) 所以为1

isKindOfClass 为1

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 老沙说点事 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 关于SRProxy
  • 关于解决方式
  • 解释NSProxy
    • 结构
      • NSProxy 和NSObject比较
        • 实验1
          • 继承NSProxy
          • 继承NSObject
        • 实验2
          • 解释
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档