ios使用NSProxy實現(xiàn)消息轉(zhuǎn)發(fā)
簡介
? 在 iOS 應(yīng)用開發(fā)中,自定義一個類一般需要繼承自 NSObject 類或者 NSObject 子類,但是,NSProxy 類不是繼承自 NSObject 類或者 NSObject 子類,而是一個實現(xiàn)了 NSObject 協(xié)議的抽象基類。
/*?? ?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 的作用就是作為一個委托代理對象,將消息轉(zhuǎn)發(fā)給一個真實的對象或者自己加載的對象。
為了進一步了解 NSProxy 類的作用,我們來實現(xiàn)一個同事調(diào)用 NSMutableString 和 NSMutableArray 兩個類中的方法的委托類,模擬多繼承。
首先創(chuàng)建 TargetProxy 類,讓他繼承 NSProxy。并實現(xiàn)初始化方法。
@interface TargetProxy : NSProxy /// 初始化方法,保存兩個真實對象 /// @param object1 第一個真實對象 /// @param object2 第二個真實對象 - (instancetype)initWithObject1:(id)object1 object2:(id)object2; @end
@implementation TargetProxy { ? ? // 保存需要將消息轉(zhuǎn)發(fā)到的第一個真實對象 ? ? // 第一個真實對象的方法調(diào)用優(yōu)先級會比第二個真實對象的方法調(diào)用優(yōu)先級高 ? ? id _realObject1; ? ? // 保存需要將消息轉(zhuǎn)發(fā)到的第二個真實對象 ? ? id _realObject2; } - (instancetype)initWithObject1:(id)object1 object2:(id)object2 { ? ? _realObject1 = object1; ? ? _realObject2 = object2; ? ?? ? ? return self; }
然后在 TargetProxy.m 文件中,重寫 - methodSignatureForSelector: 獲取真實對象方法簽名,并重寫 - forwardInvocation: 方法,調(diào)用真實的對象方法。
- (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; ? ? // 執(zhí)行方法 ? ? [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 類成功的實現(xiàn)了消息轉(zhuǎn)發(fā)。
? 當然,在大部分情況下,使用 NSObject 類也可以實現(xiàn)消息轉(zhuǎn)發(fā),實現(xiàn)方式和 NSProxy 類似,但是大部分情況下使用 NSProxy 更加合適。因為:
- NSProxy 類實現(xiàn)了包括 NSObject 協(xié)議在內(nèi)基類所需的基礎(chǔ)方法
- 通過 NSObject 類實現(xiàn)的代理類不會自動的轉(zhuǎn)發(fā) NSObject 協(xié)議中的方法
- 通過 NSObject 類實現(xiàn)的代理類不會自動的轉(zhuǎn)發(fā) NSObject 類別中的方法
到此這篇關(guān)于ios使用NSProxy實現(xiàn)消息轉(zhuǎn)發(fā)的文章就介紹到這了,更多相關(guān)ios NSProxy消息轉(zhuǎn)發(fā)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
iOS仿微博導(dǎo)航欄動畫(CoreGraphics)的實現(xiàn)方法
這篇文章主要給大家介紹了關(guān)于iOS仿微博導(dǎo)航欄動畫(CoreGraphics)的實現(xiàn)方法,文章最后給出了完整的示例代碼,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07關(guān)于ios配置微信config出現(xiàn)驗簽失敗的問題解決
這篇文章主要介紹了關(guān)于ios配置微信config出現(xiàn)驗簽失敗的問題解決方案,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-04-04iOS - UIButton(UIEdgeInsets)/設(shè)置button上的文字和圖片上下垂直居中對齊
這篇文章主要介紹了iOS - UIButton(UIEdgeInsets)/設(shè)置button上的文字和圖片上下垂直居中對齊的相關(guān)資料,需要的朋友可以參考下2015-09-09iOS開發(fā)-調(diào)用系統(tǒng)相機和相冊獲取照片示例
這篇文章主要介紹了iOS開發(fā)-調(diào)用系統(tǒng)相機和相冊獲取照片示例的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-02-02