NSProxy是啥,用来干嘛的

NSProxy是啥,用来干嘛的

​NSProxy​ ​ 是 Objective-C 中一个特殊的「替身类」,专门用来​​转发消息​ ​或​​模拟多继承​ ​。它不像普通类(如 NSObject)那样有实际功能,而是作为一个「中间人」帮你把消息转给其他对象。以下是它的核心用途和经典场景:


🎭 ​​一、NSProxy 的定位​

  • ​官方定义​​:

    NSProxy是一个抽象基类,不继承自 NSObject,但同样遵循 <NSObject>协议。

  • ​核心能力​​:

    ​转发任何消息​​(即使自己没实现),类似「消息中转站」。

  • ​特点​​:

    ✅ 轻量(比 NSObject更纯粹)

    ✅ 无 -init方法(需自定义初始化)

    ✅ 必须重写 forwardInvocation:methodSignatureForSelector:


🛠️ ​​二、NSProxy 的三大用途​

1. ​​模拟多继承(转发给多个对象)​

less 复制代码
// 定义
@interface MultiProxy : NSProxy
@property (nonatomic, strong) NSArray *targets;
@end

@implementation MultiProxy
- (void)forwardInvocation:(NSInvocation *)invocation {
    for (id target in self.targets) {
        if ([target respondsToSelector:invocation.selector]) {
            [invocation invokeWithTarget:target]; // 逐个调用
        }
    }
}
@end

// 使用
Dog *dog = [Dog new];
Cat *cat = [Cat new];
MultiProxy *proxy = [MultiProxy alloc];
proxy.targets = @[dog, cat];

[proxy performSelector:@selector(bark)]; // 调用Dog的方法
[proxy performSelector:@selector(meow)]; // 调用Cat的方法

​效果​ ​:一个 proxy同时拥有 DogCat的能力(伪多继承)。

2. ​​实现AOP(面向切面编程)​

less 复制代码
// 日志代理:在方法调用前后插入日志
@interface LogProxy : NSProxy
@property (nonatomic, weak) id target;
@end

@implementation LogProxy
- (void)forwardInvocation:(NSInvocation *)invocation {
    NSLog(@"调用前: %@", NSStringFromSelector(invocation.selector));
    [invocation invokeWithTarget:self.target]; // 调用原方法
    NSLog(@"调用后: %@", NSStringFromSelector(invocation.selector));
}
@end

// 使用
UserService *service = [UserService new];
UserService *proxy = (UserService *)[[LogProxy alloc] initWithTarget:service];
[proxy login]; // 自动输出调用日志

​用途​​:无侵入式添加日志、性能监控、权限校验等。

3. ​​延迟加载/虚拟对象​

less 复制代码
// 图片延迟加载代理
@interface LazyImageProxy : NSProxy
@property (nonatomic, strong) Class imageClass;
@property (nonatomic, strong) id realImage;
@end

@implementation LazyImageProxy
- (void)forwardInvocation:(NSInvocation *)invocation {
    if (!_realImage) {
        _realImage = [_imageClass new]; // 首次调用时创建真实对象
    }
    [invocation invokeWithTarget:_realImage]; // 转发给真实对象
}
@end

// 使用(直到调用display时才加载图片)
UIImage *proxy = (UIImage *)[[LazyImageProxy alloc] initWithClass:[UIImage class]];
[proxy display]; // 触发实际加载

​优势​​:节省内存,避免提前加载大资源。


⚠️ ​​三、注意事项​

  1. ​必须重写这两个方法​

    objectivec 复制代码
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
        // 返回一个有效的方法签名(否则崩溃)
        return [self.targets.firstObject methodSignatureForSelector:sel];
    }
    
    - (void)forwardInvocation:(NSInvocation *)invocation {
        // 实际转发逻辑
    }
  2. ​类型欺骗问题​

    • NSProxy 对象可以伪装成任何类型(如 (UIImage *)proxy),但运行时可能崩溃。
    • 建议用 respondsToSelector:提前校验。
  3. ​性能开销​

    • 每次消息转发比直接调用慢 ​10~100倍​,高频调用场景慎用。
  4. ​内存管理​

    • 若 targets 是弱引用(如 __weak),需防止对象提前释放。

📊 ​​四、NSProxy vs NSObject 消息转发​

​特性​ NSProxy NSObject 的消息转发
​设计目的​ 专为消息转发而生 通用基类,转发是附加能力
​性能​ 稍快(无NSObject开销) 略慢
​使用场景​ 纯转发代理 需继承其他功能的类
​初始化​ 需自定义 init 标准 init

💡 ​​五、经典应用案例​

  1. ​Foundation 的 NSDistantObject

    用于分布式对象通信(跨进程调用)。

  2. ​AFNetworking 2.x 的 AFHTTPRequestOperation

    用 Proxy 管理网络请求的回调。

  3. ​RAC 的 RACProxy

    实现 ReactiveCocoa 的信号转发。


🌟 ​​总结​

  • ​NSProxy 是消息转发的专业户​​,适合:

    ✅ 模拟多继承

    ✅ AOP 无侵入扩展

    ✅ 虚拟化/延迟加载

  • ​不要用它继承业务逻辑​ ​,普通类还是选 NSObject

  • ​Swift 替代方案​​:

    Protocol ExtensionCombinePublisher实现类似功能。

相关推荐
2501_915909063 小时前
iOS 应用反调试技详解术 检测调试器的原理与防护实践
android·ios·小程序·https·uni-app·iphone·webview
游戏开发爱好者84 小时前
TraceEagle 代理抓包详解,无感代理、去证书绑定与 HTTP/3 解密能力解析
网络协议·计算机网络·网络安全·ios·adb·https·udp
aiopencode5 小时前
SwiftUI Introspect生产环境完全指南:为什么它是安全可靠的选择
后端·ios
for_ever_love__6 小时前
iOS: 网络管理单例
学习·ios·objective-c
00后程序员张6 小时前
iOS加固技术路线全面解析:Bitcode模式、源码模式与汇编模式对比及爱加密优势
android·汇编·ios·小程序·uni-app·cocoa·iphone
ii_best16 小时前
更新!移动端开发软件按键安卓版&手机助手v5.1.0上线!本地AI识别全面解锁,脚本开发再升级
android·人工智能·ios·按键精灵
weixin_4038101320 小时前
03-iOS免越狱无线投屏-上传图片和视频到相册
ios·新媒体运营·跨境电商·ios自动化·ios投屏·ios智能体·ios脚本
2501_9160074720 小时前
SwiftUI 声明式语法与 Xcode 预览功能详解
ide·vscode·ios·swiftui·个人开发·xcode·敏捷流程
2501_916008891 天前
iOS IPA文件反编译与打包操作方法,拆包分析防护和加固打包
android·macos·ios·小程序·uni-app·cocoa·iphone
码云数智-大飞1 天前
iOS 卡顿排查指南:主线程阻塞与 UI 渲染优化实战
ui·ios