如何通过NSProxy实现消息转发来处理长尾词的?

2026-04-11 10:461阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1003个文字,预计阅读时间需要5分钟。

如何通过NSProxy实现消息转发来处理长尾词的?

一、简介在iOS应用开发中,自定义一个类通常需要继承自NSObject或其子类。然而,NSProxy类并非继承自NSObject或其子类,而是实现了NSObject协议的一个抽象基类。

二、NSProxy类NSProxy类是一个抽象基类,它不继承自NSObject或其子类,但实现了NSObject协议。这意味着任何使用NSProxy的对象都可以响应Objective-C的消息,尽管它们没有继承自NSObject。这使得NSProxy成为一个强大的工具,可以用于创建轻量级的代理对象,实现类似于委托(delegation)的功能。

一、简介

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

/* NSProxy.h Copyright (c) 1994-2019, Apple Inc. All rights reserved. */ #import <Foundation/NSObject.h> @class NSMethodSignature, NSInvocation; NS_ASSUME_NONNULL_BEGIN NS_ROOT_CLASS @interface NSProxy <NSObject> { __ptrauth_objc_isa_pointer Class isa; } + (id)alloc; + (id)allocWithZone:(nullable NSZone *)zone NS_AUTOMATED_REFCOUNT_UNAVAILABLE; + (Class)class; - (void)forwardInvocation:(NSInvocation *)invocation; - (nullable NSMethodSignature *)methodSignatureForSelector:(SEL)sel NS_SWIFT_UNAVAILABLE("NSInvocation and related APIs not available"); - (void)dealloc; - (void)finalize; @property (readonly, copy) NSString *description; @property (readonly, copy) NSString *debugDescription; + (BOOL)respondsToSelector:(SEL)aSelector; - (BOOL)allowsWeakReference API_UNAVAILABLE(macos, ios, watchos, tvos); - (BOOL)retainWeakReference API_UNAVAILABLE(macos, ios, watchos, tvos); // - (id)forwardingTargetForSelector:(SEL)aSelector; @end NS_ASSUME_NONNULL_END

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

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

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

@interface TargetProxy : NSProxy /// 初始化方法,保存两个真实对象 /// @param object1 第一个真实对象 /// @param object2 第二个真实对象 - (instancetype)initWithObject1:(id)object1 object2:(id)object2; @end

@implementation TargetProxy { // 保存需要将消息转发到的第一个真实对象 // 第一个真实对象的方法调用优先级会比第二个真实对象的方法调用优先级高 id _realObject1; // 保存需要将消息转发到的第二个真实对象 id _realObject2; } - (instancetype)initWithObject1:(id)object1 object2:(id)object2 { _realObject1 = object1; _realObject2 = object2; return self; }

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

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel { // 获取 _realObject1 中 sel 的方法签名 NSMethodSignature *signature = [_realObject1 methodSignatureForSelector:sel]; // 如果 _realObject1 中有该方法,那么返回该方法的签名 // 如果没有,返回 _realObject1 方法签名 if (signature) { return signature; } // 获取 _realObject1 中的 sel 的方法签名 signature = [_realObject2 methodSignatureForSelector:sel]; return signature; } - (void)forwardInvocation:(NSInvocation *)invocation { // 获取拥有该方法的真实对象 id target = [_realObject1 methodSignatureForSelector:[invocation selector]] ? _realObject1 : _realObject2; // 执行方法 [invocation invokeWithTarget:target]; }

最后,进行 Demo 测试

- (void)testTargetProxy { NSMutableString *string = [NSMutableString string]; NSMutableArray *array = [NSMutableArray array]; id proxy = [[TargetProxy alloc] initWithObject1:string object2:array]; [proxy appendString:@"This "]; [proxy appendString:@"is "]; [proxy addObject:string]; [proxy appendString:@"a "]; [proxy appendString:@"test!"]; NSLog(@"The string is length is: %@", [proxy valueForKey:@"length"]); NSLog(@"count should be 1, it is %ld", [proxy count]); if ([[proxy objectAtIndex:0] isEqualToString:@"This is a test!"]) { NSLog(@"Appending successful."); } else { NSLog(@"Appending failed,, got: '%@'", proxy); } }

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

如何通过NSProxy实现消息转发来处理长尾词的?

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 类别中的方法

本文共计1003个文字,预计阅读时间需要5分钟。

如何通过NSProxy实现消息转发来处理长尾词的?

一、简介在iOS应用开发中,自定义一个类通常需要继承自NSObject或其子类。然而,NSProxy类并非继承自NSObject或其子类,而是实现了NSObject协议的一个抽象基类。

二、NSProxy类NSProxy类是一个抽象基类,它不继承自NSObject或其子类,但实现了NSObject协议。这意味着任何使用NSProxy的对象都可以响应Objective-C的消息,尽管它们没有继承自NSObject。这使得NSProxy成为一个强大的工具,可以用于创建轻量级的代理对象,实现类似于委托(delegation)的功能。

一、简介

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

/* NSProxy.h Copyright (c) 1994-2019, Apple Inc. All rights reserved. */ #import <Foundation/NSObject.h> @class NSMethodSignature, NSInvocation; NS_ASSUME_NONNULL_BEGIN NS_ROOT_CLASS @interface NSProxy <NSObject> { __ptrauth_objc_isa_pointer Class isa; } + (id)alloc; + (id)allocWithZone:(nullable NSZone *)zone NS_AUTOMATED_REFCOUNT_UNAVAILABLE; + (Class)class; - (void)forwardInvocation:(NSInvocation *)invocation; - (nullable NSMethodSignature *)methodSignatureForSelector:(SEL)sel NS_SWIFT_UNAVAILABLE("NSInvocation and related APIs not available"); - (void)dealloc; - (void)finalize; @property (readonly, copy) NSString *description; @property (readonly, copy) NSString *debugDescription; + (BOOL)respondsToSelector:(SEL)aSelector; - (BOOL)allowsWeakReference API_UNAVAILABLE(macos, ios, watchos, tvos); - (BOOL)retainWeakReference API_UNAVAILABLE(macos, ios, watchos, tvos); // - (id)forwardingTargetForSelector:(SEL)aSelector; @end NS_ASSUME_NONNULL_END

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

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

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

@interface TargetProxy : NSProxy /// 初始化方法,保存两个真实对象 /// @param object1 第一个真实对象 /// @param object2 第二个真实对象 - (instancetype)initWithObject1:(id)object1 object2:(id)object2; @end

@implementation TargetProxy { // 保存需要将消息转发到的第一个真实对象 // 第一个真实对象的方法调用优先级会比第二个真实对象的方法调用优先级高 id _realObject1; // 保存需要将消息转发到的第二个真实对象 id _realObject2; } - (instancetype)initWithObject1:(id)object1 object2:(id)object2 { _realObject1 = object1; _realObject2 = object2; return self; }

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

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel { // 获取 _realObject1 中 sel 的方法签名 NSMethodSignature *signature = [_realObject1 methodSignatureForSelector:sel]; // 如果 _realObject1 中有该方法,那么返回该方法的签名 // 如果没有,返回 _realObject1 方法签名 if (signature) { return signature; } // 获取 _realObject1 中的 sel 的方法签名 signature = [_realObject2 methodSignatureForSelector:sel]; return signature; } - (void)forwardInvocation:(NSInvocation *)invocation { // 获取拥有该方法的真实对象 id target = [_realObject1 methodSignatureForSelector:[invocation selector]] ? _realObject1 : _realObject2; // 执行方法 [invocation invokeWithTarget:target]; }

最后,进行 Demo 测试

- (void)testTargetProxy { NSMutableString *string = [NSMutableString string]; NSMutableArray *array = [NSMutableArray array]; id proxy = [[TargetProxy alloc] initWithObject1:string object2:array]; [proxy appendString:@"This "]; [proxy appendString:@"is "]; [proxy addObject:string]; [proxy appendString:@"a "]; [proxy appendString:@"test!"]; NSLog(@"The string is length is: %@", [proxy valueForKey:@"length"]); NSLog(@"count should be 1, it is %ld", [proxy count]); if ([[proxy objectAtIndex:0] isEqualToString:@"This is a test!"]) { NSLog(@"Appending successful."); } else { NSLog(@"Appending failed,, got: '%@'", proxy); } }

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

如何通过NSProxy实现消息转发来处理长尾词的?

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 类别中的方法