经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » iOS » 查看文章
ios使用NSProxy实现消息转发
来源:jb51  时间:2022/7/4 12:09:46  对本文有异议

简介

? 在 iOS 应用开发中,自定义一个类一般需要继承自 NSObject 类或者 NSObject 子类,但是,NSProxy 类不是继承自 NSObject 类或者 NSObject 子类,而是一个实现了 NSObject 协议的抽象基类。

  1. /*?? ?NSProxy.h
  2. ?? ?Copyright (c) 1994-2019, Apple Inc. All rights reserved.
  3. */
  4.  
  5. #import <Foundation/NSObject.h>
  6.  
  7. @class NSMethodSignature, NSInvocation;
  8.  
  9. NS_ASSUME_NONNULL_BEGIN
  10.  
  11. NS_ROOT_CLASS
  12. @interface NSProxy <NSObject> {
  13. ? ? __ptrauth_objc_isa_pointer Class?? ?isa;
  14. }
  15.  
  16. + (id)alloc;
  17. + (id)allocWithZone:(nullable NSZone *)zone NS_AUTOMATED_REFCOUNT_UNAVAILABLE;
  18. + (Class)class;
  19.  
  20. - (void)forwardInvocation:(NSInvocation *)invocation;
  21. - (nullable NSMethodSignature *)methodSignatureForSelector:(SEL)sel NS_SWIFT_UNAVAILABLE("NSInvocation and related APIs not available");
  22. - (void)dealloc;
  23. - (void)finalize;
  24. @property (readonly, copy) NSString *description;
  25. @property (readonly, copy) NSString *debugDescription;
  26. + (BOOL)respondsToSelector:(SEL)aSelector;
  27.  
  28. - (BOOL)allowsWeakReference API_UNAVAILABLE(macos, ios, watchos, tvos);
  29. - (BOOL)retainWeakReference API_UNAVAILABLE(macos, ios, watchos, tvos);
  30.  
  31. // - (id)forwardingTargetForSelector:(SEL)aSelector;
  32.  
  33. @end
  34.  
  35. NS_ASSUME_NONNULL_END

NSProxy 的作用就是作为一个委托代理对象,将消息转发给一个真实的对象或者自己加载的对象。

为了进一步了解 NSProxy 类的作用,我们来实现一个同事调用 NSMutableString 和 NSMutableArray 两个类中的方法的委托类,模拟多继承。

首先创建 TargetProxy 类,让他继承 NSProxy。并实现初始化方法。

  1. @interface TargetProxy : NSProxy
  2.  
  3.  
  4. /// 初始化方法,保存两个真实对象
  5. /// @param object1 第一个真实对象
  6. /// @param object2 第二个真实对象
  7. - (instancetype)initWithObject1:(id)object1 object2:(id)object2;
  8.  
  9. @end
  1. @implementation TargetProxy {
  2.  
  3. ? ? // 保存需要将消息转发到的第一个真实对象
  4. ? ? // 第一个真实对象的方法调用优先级会比第二个真实对象的方法调用优先级高
  5. ? ? id _realObject1;
  6. ? ? // 保存需要将消息转发到的第二个真实对象
  7. ? ? id _realObject2;
  8. }
  9.  
  10. - (instancetype)initWithObject1:(id)object1 object2:(id)object2 {
  11. ? ? _realObject1 = object1;
  12. ? ? _realObject2 = object2;
  13. ? ??
  14. ? ? return self;
  15. }

然后在 TargetProxy.m 文件中,重写 - methodSignatureForSelector: 获取真实对象方法签名,并重写 - forwardInvocation: 方法,调用真实的对象方法。

  1. - (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
  2. ? ? // 获取 _realObject1 中 sel 的方法签名
  3. ? ? NSMethodSignature *signature = [_realObject1 methodSignatureForSelector:sel];
  4. ? ? // 如果 _realObject1 中有该方法,那么返回该方法的签名
  5. ? ? // 如果没有,返回 _realObject1 方法签名
  6. ? ? if (signature) {
  7. ? ? ? ? return signature;
  8. ? ? }
  9. ? ? // 获取 _realObject1 中的 sel 的方法签名
  10. ? ? signature = [_realObject2 methodSignatureForSelector:sel];
  11. ? ? return signature;
  12. }
  13.  
  14. - (void)forwardInvocation:(NSInvocation *)invocation {
  15. ? ? // 获取拥有该方法的真实对象
  16. ? ? id target = [_realObject1 methodSignatureForSelector:[invocation selector]] ? _realObject1 : _realObject2;
  17.  
  18. ? ? // 执行方法
  19. ? ? [invocation invokeWithTarget:target];
  20. }

最后,进行 Demo 测试

  1. - (void)testTargetProxy {
  2. ? ? NSMutableString *string = [NSMutableString string];
  3. ? ? NSMutableArray *array = [NSMutableArray array];
  4. ? ??
  5. ? ? id proxy = [[TargetProxy alloc] initWithObject1:string object2:array];
  6. ? ? [proxy appendString:@"This "];
  7. ? ? [proxy appendString:@"is "];
  8. ? ? [proxy addObject:string];
  9. ? ? [proxy appendString:@"a "];
  10. ? ? [proxy appendString:@"test!"];
  11. ? ??
  12. ? ? NSLog(@"The string is length is: %@", [proxy valueForKey:@"length"]);
  13. ? ? NSLog(@"count should be 1, it is %ld", [proxy count]);
  14. ? ??
  15. ? ? if ([[proxy objectAtIndex:0] isEqualToString:@"This is a test!"]) {
  16. ? ? ? ? NSLog(@"Appending successful.");
  17. ? ? } else {
  18. ? ? ? ? NSLog(@"Appending failed,, got: '%@'", proxy);
  19. ? ? }
  20. }

运行上面的代码,输入日志如下:

2022-04-02 11:30:35.957145+0800 Demo[19783:586710] SuccessFully create Delegere Proxy automatically.
2022-04-02 11:30:35.959722+0800 Demo[19783:586710] The string is length is: 15
2022-04-02 11:30:35.960175+0800 Demo[19783:586710] count should be 1, it is 1
2022-04-02 11:30:40.086227+0800 Demo[19783:586710] Appending successful.

? 以上说明,我们使用 TargetProxy 类成功的实现了消息转发。

? 当然,在大部分情况下,使用 NSObject 类也可以实现消息转发,实现方式和 NSProxy 类似,但是大部分情况下使用 NSProxy 更加合适。因为:

  • NSProxy 类实现了包括 NSObject 协议在内基类所需的基础方法
  • 通过 NSObject 类实现的代理类不会自动的转发 NSObject 协议中的方法
  • 通过 NSObject 类实现的代理类不会自动的转发 NSObject 类别中的方法

 到此这篇关于ios使用NSProxy实现消息转发的文章就介绍到这了,更多相关ios NSProxy消息转发内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号