CTNetworking源码拾遗
2016-09-05 本文已影响944人
AliThink
一句话简介: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 ?? "为空的时候我就派上用场啦"