網站首頁 編程語言 正文
簡介
? 在 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);
? ? }
}
運行上面的代碼,輸入日志如下:
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 類別中的方法
原文鏈接:https://www.cnblogs.com/r360/p/16441909.html
相關推薦
- 2022-10-07 mybatis?調用?Oracle?存儲過程并接受返回值的示例代碼_oracle
- 2022-11-09 Python?Pandas讀寫txt和csv文件的方法詳解_python
- 2022-12-23 Kubernetes應用配置管理創建使用詳解_云其它
- 2022-11-05 Nginx配置文件中location配置的多種場景_nginx
- 2023-05-09 python中類的相互調用的實踐_python
- 2023-03-13 Android?Hilt依賴注入的使用講解_Android
- 2022-10-29 Android 開發 | API 指南- Content Provider 應用程序的使用方法
- 2023-07-22 BeanFactory和FactoryBean區別
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支