一句話簡介:CTNetworking為casa大神針對iOS網絡層方案的一個架構實例。
架構詳解: 傳送門
Github: 傳送門
PS: 本拾遺系列文章只專注于代碼以及工程層面知識點拾遺,架構層面作者文章已經進行了詳細的講解。
1. 宏相關
-
預防重復引入導致的重定義問題:
#ifndef CTNetworking_CTNetworkingConfiguration_h #define CTNetworking_CTNetworkingConfiguration_h typedef NS_ENUM(NSInteger, CTAppType) { CTAppTypexxx }; ... static NSString *CTKeychainServiceName = @"xxxxx"; ... extern NSString * const kCTServiceGDMapV3; #endif
CTNetworking_CTNetworkingConfiguration_h這塊的命名沒有什么特別的規范,往往是將點替換為下劃線,開頭添加一條下劃線。(casa這里是在最前面又加了工程名,AFNetworking則是省略了擴展名)
-
巧妙的宏替換:
#define AXCallAPI(REQUEST_METHOD, REQUEST_ID)\ {\ __weak typeof(self) weakSelf = self;\ REQUEST_ID = [[CTApiProxy sharedInstance] call##REQUEST_METHOD##WithParams:apiParams serviceIdentifier:self.child.serviceType methodName:self.child.methodName success:^(CTURLResponse *response) {\ __strong typeof(weakSelf) strongSelf = weakSelf;\ [strongSelf successedOnCallingAPI:response];\ } fail:^(CTURLResponse *response) {\ __strong typeof(weakSelf) strongSelf = weakSelf;\ [strongSelf failedOnCallingAPI:response withErrorType:CTAPIManagerErrorTypeDefault]; \ }];\ [self.requestIdList addObject:@(REQUEST_ID)];\ } // 通過##REQUEST_METHOD##包裹的變量將進行宏替換,進而達到根據約定區分方法調用的目的
2. UDID
常規的UUID+keychain的策略:
-
創建
- (NSString *)CT_createUUID { CFUUIDRef uuid = CFUUIDCreate(NULL); CFStringRef string = CFUUIDCreateString(NULL, uuid); CFRelease(uuid); return (__bridge_transfer NSString *)string; }
-
保存讀取
- (void)saveUDID:(NSString *)udid { BOOL saveOk = NO; NSData *udidData = [self searchKeychainCopyMatching:CTUDIDName]; if (udidData == nil) { saveOk = [self createKeychainValue:udid forIdentifier:CTUDIDName]; }else{ saveOk = [self updateKeychainValue:udid forIdentifier:CTUDIDName]; } if (!saveOk) { [self createPasteBoradValue:udid forIdentifier:CTUDIDName]; } } - (NSString *)UDID { NSData *udidData = [self searchKeychainCopyMatching:CTUDIDName]; NSString *udid = nil; if (udidData != nil) { NSString *temp = [[NSString alloc] initWithData:udidData encoding:NSUTF8StringEncoding]; udid = [NSString stringWithFormat:@"%@", temp]; } if (udid.length == 0) { udid = [self readPasteBoradforIdentifier:CTUDIDName]; } return udid; }
3. 內存管理權轉移標記
- __bridge: 不涉及管理所有權的轉移。
- __bridge_transfer: CF對象轉成OC對象時,順便交出內存管理權。(ARC)
- __bridge_retained: OC對象轉成CF對象時,順便交出內存管理權。(CFRelease(xxx))
4. DECORATOR PATTERN小解
decorator.jpg
適用場景:
在不影響其他對象的情況下,以動態、透明的方式給單個對象添加職責。
處理那些可以撤消的職責。
-
當不能采用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴展,為支持每一種組合將產生大量的子類,使得子類數目呈爆炸性增長。另一種情況可能是因為類定義被隱藏,或類定義不能用于生成子類。
一個專門講解OC設計模式的開源庫—傳送門
5. 閉包的三元操作
fail?fail(CTResponse):nil
6. 封裝一個統一的空值處理
#import "NSObject+AXNetworkingMethods.h"
@implementation NSObject (AXNetworkingMethods)
- (id)CT_defaultValue:(id)defaultData
{
if (![defaultData isKindOfClass:[self class]]) {
return defaultData;
}
if ([self CT_isEmptyObject]) {
return defaultData;
}
return self;
}
- (BOOL)CT_isEmptyObject
{
if ([self isEqual:[NSNull null]]) {
return YES;
}
if ([self isKindOfClass:[NSString class]]) {
if ([(NSString *)self length] == 0) {
return YES;
}
}
if ([self isKindOfClass:[NSArray class]]) {
if ([(NSArray *)self count] == 0) {
return YES;
}
}
if ([self isKindOfClass:[NSDictionary class]]) {
if ([(NSDictionary *)self count] == 0) {
return YES;
}
}
return NO;
}
@end
如果要是Swift的話其實就不用這么搞啦_
optionalVarA ?? "為空的時候我就派上用場啦"