? ? ? ? ?
(一)覆蓋主類的方法實(shí)現(xiàn)
? XMPP的IPV6適配
蘋果要適配IPV6(only)了,查了一下網(wǎng)上的方法,基本上是在GCDAsyncSocket中改動。這樣有個缺點(diǎn);庫更新的時候之前的改動失效痪蝇。而且一般不建議在第三庫里面改鄙陡。剛好GCDAsyncSocket的的原方法是直接調(diào)用另一個方法。
上代碼:
#import "GCDAsyncSocket+ECBIPV6.h"
#import "ECBIPV6SocketTransfer.h"
@implementation GCDAsyncSocket (ECBIPV6)
-(BOOL)connectToHost:(NSString *)host onPort:(uint16_t)port error:(NSError *__autoreleasing *)errPtr
{
//地址轉(zhuǎn)換躏啰,代碼就不貼了
NSString *newhost=[ECBIPV6SocketTransfer convertHostToAddress:host];
return? [self connectToHost:newhost onPort:port withTimeout:-1 error:errPtr];
}
@end
GCDAsyncSocket的原方法:
- (BOOL)connectToHost:(NSString*)host onPort:(uint16_t)port error:(NSError **)errPtr
{
return [self connectToHost:host onPort:port withTimeout:-1 error:errPtr];
}
? category覆蓋主類方法切記要注意的一點(diǎn)是趁矾,不管有沒有導(dǎo)入頭文件,都會覆蓋主類的方法给僵。具體原因這里不展開說毫捣,如要詳細(xì)了解,請看雷純鋒的博客:Objective-C Category 的實(shí)現(xiàn)原理
(二)使用protocol調(diào)用類的隱藏方法
NSobject+YYModel的以其人之道還治其人之身
? 之前一直在用YYModel的+ (NSArray *)modelArrayWithClass:(Class)cls array:(NSArray *)arr方法想际,后來項(xiàng)目中導(dǎo)入了YYKit就把YYModel刪了培漏,直接用YYkit中的NSobject+YYModel。蛋疼的是頭文件里只公開了+ (NSArray *)modelArrayWithClass:(Class)cls json:(id)json胡本。所以用的時候把a(bǔ)rray轉(zhuǎn)換成json再調(diào)用牌柄。但是方法實(shí)現(xiàn)里卻是+ (NSArray *)modelArrayWithClass:(Class)cls json:(id)json將json轉(zhuǎn)化成array再調(diào)用+ (NSArray *)modelArrayWithClass:(Class)cls array:(NSArray *)arr。侧甫。珊佣。。披粟,是不是大寫的懵逼咒锻。
? 當(dāng)然最簡單的方法是直接將+ (NSArray *)modelArrayWithClass:(Class)cls array:(NSArray *)arr放在頭文件中,但是秉著不改第三方庫的原則守屉,我并沒有這樣做惑艇。?
? 往深處說,其實(shí)OC中沒有隱藏方法拇泛,使用蠻力一樣能調(diào)用頭文件沒有公開的方法滨巴。但這樣一點(diǎn)都不能體現(xiàn)文章的主題:妙用。俺叭。恭取。
?YYModel中有個適配屬性鍵值得方法:+ (NSDictionary *)modelCustomPropertyMapper,這個方法并不要求寫在頭文件中熄守◎诳澹看了源代碼才發(fā)現(xiàn),作者在NSObject分類中定義了一個協(xié)議:
@protocol YYModel
@optional
+ (nullable NSDictionary*)modelCustomPropertyMapper;
看到這里裕照,似乎明白什么了攒发,我馬上也在NSArray,NSDictionary的分類中定義了一個協(xié)議并遵循它
貼出NSArray+ECB.h中的部分代碼
@protocol ECBYYModelArrayProtocol
@optional
+ (NSArray *)modelArrayWithClass:(Class)cls array:(NSArray *)arr;
@end
@interface NSArray (ECB)<ECBYYModelArrayProtocol>
+(NSArray*)yy_modelArrayWithClass:(Class)cls array:(NSArray*)listArray;
NSArray+ECB.m中的實(shí)現(xiàn)
+(NSArray*)yy_modelArrayWithClass:(Class)cls array:(NSArray*)listArray
{
return [NSArray modelArrayWithClass:cls array:listArray ];
}
ps:這條后來看下基本沒什么用
直接在分類頭文件中聲明方法也行,不好意思
(三)使用運(yùn)行時重新定義容器的debugDescription
當(dāng)數(shù)組中元素是OC對象的時候晋南,NSLog或斷點(diǎn)Debug用po輸出的時候晨继,顯示的只有類名和地址。
如果想看到每個元素的屬性和屬性值搬俊,可以在分類中實(shí)現(xiàn)debugDescription或Description
這里就要用到運(yùn)行時遍歷對象的屬性
代碼如下:
- (NSString *)debugDescription
{
__block NSString *debugstring = @"";
[self enumerateObjectsUsingBlock:^(id? _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList([obj class], &outCount);
NSMutableDictionary *dict =[NSMutableDictionary dictionary];
? ? for (i = 0; i<outCount;i++){
? ? objc_property_t property = properties[i];
? ?const char* char_f =property_getName(property);
? NSString *propertyName = [NSString stringWithUTF8String:char_f];
? id propertyValue = [obj valueForKey:propertyName];
? if (propertyValue) [dict setObject:propertyValue forKey:propertyName ];
? ? }
?free(properties);
debugstring =[debugstring stringByAppendingString:[NSString stringWithFormat:@"%lu,<%@,%p>,%@\n\n",idx,[obj class],&obj,dict]];
}];
return debugstring;
}
測試效果如下: