前言的前言
經(jīng)過一些思考和反省抵皱,感覺平時只記錄東西在腦中善榛,年紀大了,淡忘了很多呻畸。so移盆,準(zhǔn)備以此為平臺記錄下,造福自己擂错,當(dāng)然如果有讀者能夠獲益味滞,那也是極好的。
文筆不好钮呀,也不喜歡長篇大論剑鞍。講些別人沒表述的以及自己的一些領(lǐng)悟。
本人技術(shù)能力一般爽醋,可能存在理解上的錯誤蚁署,所以歡迎大家留言指正。
本文前言
NSProxy蚂四,一個特殊的存在光戈,所謂的抽象類。一班人用的很少遂赠,三年二班的其實用的也不多久妆。
一個概念性的類,近期想解決一個iPhone跷睦、iPad的適配問題筷弦,突然回想起了它。簡單介紹下,合作的同學(xué)做了2個view烂琴,一個4iPhone爹殊、一個4iPad,他們使用了同樣的function奸绷、property梗夸,就是類名不一樣,而且2者也沒有繼承關(guān)系号醉。(內(nèi)心的os就是:你這個坑我跳的爽)反症。
思路是利用一個對象,在不同的環(huán)境下指向到不同的view扣癣。如果更進一步惰帽,我想到了NSProxy憨降。當(dāng)然最終是實現(xiàn)了的父虑,本文的詳細內(nèi)容是在事后重新梳理的實現(xiàn)方式。
一授药、概述
從各種教程上大家可以理解NSProxy有以下特點:
- 不繼承NSObject士嚎,即不是NSObject。
- 遵循了NSObject協(xié)議悔叽。(和上面一點的區(qū)別自己領(lǐng)悟莱衩,繼承和協(xié)議)。
- 解決多繼承問題娇澎。
- 解決弱引用問題笨蚁。
- 未完待續(xù),可能存在我還不了解的點趟庄。
二括细、代碼示例
一個可用的weakProxy,用以解決NSTimer和controller之間的循環(huán)引用問題戚啥。
聲明
@interface BWeakProxy : NSProxy
+ (nonnull instancetype)proxyWithTargetObject:(nullable id)targetObject;
- (void)setTargetObject:(nullable id)targetObject;
- (nullable id)targetObject;
@end
實現(xiàn)
@implementation BWeakProxy {
__weak id _targetObject;
}
+ (nonnull instancetype)proxyWithTargetObject:(nullable id)targetObject {
id proxy = [self alloc];
[proxy setTargetObject:targetObject];
return proxy;
}
- (void)setTargetObject:(nullable id)targetObject {
_targetObject = targetObject;
}
- (nullable id)targetObject {
return _targetObject;
}
- (void)forwardInvocation:(NSInvocation *)invocation {
if ([_targetObject respondsToSelector:invocation.selector]) {
[invocation invokeWithTarget:_targetObject];
}
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
NSMethodSignature *signature = nil;
if ([_targetObject respondsToSelector:sel]) {
signature = [_targetObject methodSignatureForSelector:sel];
} else {
// 動態(tài)造一個 void object selector arg 函數(shù)簽名奋单。
// 目的是返回有效signature,不要因為找不到而crash
signature = [NSMethodSignature signatureWithObjCTypes:"v@:@"];
}
return signature;
}
@end
調(diào)用
[NSTimer scheduledTimerWithTimeInterval:3.0f target:[BWeakProxy proxyWithTargetObject:self] selector:@selector(timerInvoke) userInfo:nil repeats:YES];
三猫十、要點
沒有太多分析览濒,只想說說最重要的部分。
1. methodSignatureForSelector的實現(xiàn)細節(jié)
有2步拖云,首先判斷了被代理對象是否含有相關(guān)的selector贷笛。如果有,你自然懂的宙项。
如果沒有乏苦,那么問題來了。一般我們會返回nil杉允,而這個時候系統(tǒng)會出現(xiàn)
doesnotrecognizeselector
的相關(guān)錯誤邑贴。經(jīng)過猜想席里,感覺蘋果的初衷是,有實際方法就調(diào)用拢驾,沒有的話就拋異常奖磁,目的是讓用戶明確的調(diào)用。但是一般我們使用代理繁疤,希望溫柔點咖为。有就執(zhí)行,如果沒有稠腊,就不執(zhí)行躁染,別讓我crash了。所以在這里架忌,我手動建立了一個
signature = [NSMethodSignature signatureWithObjCTypes:"v@:@"];
這個signature
是會被傳到后面的forwardInvocation
的invocation
中吞彤。不過forwardInvocation
的處理我們關(guān)注的還是selector,所以這個臨時signature
也沒什么作用了叹放,就是不要在意了饰恕。
2. weak target
__weak id _targetObject;
- 這里必須是weak,否則就會循環(huán)引用了井仰。
- 一般同學(xué)習(xí)慣使用weak的property埋嵌。不過我個人更傾向使用成員變量,理由么俱恶,我總希望暴露的東西越少越好雹嗦。
四、其他
文章寫的很潦草合是,如果你感興趣卻有疑問了罪,可以隨意留言。我會盡快完善端仰。
至于NSProxy的其他應(yīng)用比如多繼承捶惜,暫時沒有實現(xiàn),看以后的機緣了荔烧。
目前沒有g(shù)ithub吱七,之后應(yīng)該會完整工程放上去。
感謝你的閱讀鹤竭!