NSProxy 一些 使用

一、内容

  • NSProxy 是什么?
  • 消息转发机制
  • NSProxy 和 NSObject 的比较
  • 解决 CADisplayLink ,NSTimer强引用target引起的无法释放问题。

二、NSProxy 含义

  • NSProxy 是跟 NSObject 一样的基类,都遵守协议
  • NSProxy是一个抽象类,必须继承实例化其子类才能使用。
  • NSProxy从类名来看是代理类专门负责代理对象转发消息的。相比NSObject类来说NSProxy更轻量级,通过NSProxy可以帮助Objective-C间接的实现多重继承的功能。

三、消息转发机制
当程序运行时调用一个没有实现的方法,会采用三个消息转发步骤如果这三个步骤都不能成功那么此时程序会抛出一个异常。

1.添加方法到类对象,对于实例方法调用respondsToSelector:,对于类方法调用resolveClassMethod:

+(BOOL)resolveClassMethod:(SEL)sel;
-(BOOL)respondsToSelector:(SEL)aSelector;

2.查找forwardingTargetForSelector:方法,该方法返回一个新对象,如果返回nil那么将跳转到下一步骤。

-(id)forwardingTargetForSelector:(SEL)aSelector;

3.通过methodSignatureForSelector:方法获取一个NSMethodSignature类型的对象,调用forwardInvocation:方法。改方法传入一个封装了NSMethodSignatureNSInvocation对象。然后该对象通过invakeWithTarget:方法将消息转发给其它对象。

-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;
- (void)forwardInvocation:(NSInvocation *)invocation;

四、 NSProxy 和 NSObject 的比较

  • 使用 NSProxy 做消息转发 比 使用 NSObject 效率高。

当这两个类都没有执行消息转发时,会报什么样的错误?

  • NSProxy 会直接报 methodSignatureForSelector 方法错误
  • NSObject 会报 [NSObject timerTest] 没有找到 错误

他们两个的执行流程:

  • 继承至 NSObject 的类:
    • 先去类对象里面找 -> 父类的类对象找 -> 缓存中 -> 搜索
  • 继承至 NSProxy 的类:
    • 先会在本类中找,如果没有直接消息转发。不会去 类对象找,父类的类对象中找。

isKindOfClass 方法的比较:
NSProxy 一些 使用_第1张图片

执行结果: 1 ,0

解释:
1、 isKindOfClass : 检查 左边 是否是 右边的 类型或 子类

2、为什么 proxy2 打印结果是0

  • 这是因为 proxy 的类型是 MJProxy1 类型, WYProxy1 类型 继承至 NSObject
  • 也就是说 proxy2 是继承至 NSObject 。说明 proxy2 是 普通的 OC 对象。
  • 那么 isKindOfClass 就按照普通 OC 对象处理 。NSObject != viewController 类型 所以 打印为0

3、那为什么 proxy1 打印结果是1

  • 因为 proxy1 的类型是 WYProxy2 .WYProxy2 继承至 NSProxy .
  • 只要是继承至 NSProxy ,那么大部分就会进入消息转发阶段。
  • 也就意味着,在 调用 isKindOfClass 的时候,也进入了消息转发。就会进入到 methodSignatureForSelectorforwardInvocation 这两个方法。
  • 它的调用顺序就改成了 target 。也就是说先拿到[WYProxy proxyWithtarget: vc] 中的 vc .
  • 然后[proxy1 isKindOfClass:[ViewController class]] 变成了[vc isKindOfClass:[ViewController class]];

五 、 解决 CADisplayLink ,NSTimer强引用target引起的无法释放问题。
参考 内存管理:CADisplayLink、NSTimer、NSProxy 使用注意


参考:
利用NSProxy解决NSTimer内存泄漏问题

多重继承、延迟初始化、代理方法

你可能感兴趣的:(iOS底层)