CTNetworking源码拾遗
一句话简介:CTNetworking为casa大神针对iOS网络层方案的一个架构实例。
架构详解: 传送门
Github: 传送门
PS: 本拾遗系列文章只专注于代码以及工程层面知识点拾遗,架构层面作者文章已经进行了详细的讲解。
1. 宏相关
预防重复引入导致的重定义问题:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#ifndef CTNetworking_CTNetworkingConfiguration_h
#define CTNetworking_CTNetworkingConfiguration_h
typedef NS_ENUM(NSInteger, CTAppType) {
CTAppTypexxx
};
...
static NSString *CTKeychainServiceName = @"xxxxx";
...
extern NSString * const kCTServiceGDMapV3;
#endifCTNetworking_CTNetworkingConfiguration_h这块的命名没有什么特别的规范,往往是将点替换为下划线,开头添加一条下划线。(casa这里是在最前面又加了工程名,AFNetworking则是省略了扩展名)
巧妙的宏替换:
1
2
3
4
5
6
7
8
9
10
11
12
13
14#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的策略:
创建
1
2
3
4
5
6
7- (NSString *)CT_createUUID
{
CFUUIDRef uuid = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, uuid);
CFRelease(uuid);
return (__bridge_transfer NSString *)string;
}保存读取
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27- (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小解

适用场景:
在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
处理那些可以撤消的职责。
当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
一个专门讲解OC设计模式的开源库—传送门
5. 闭包的三元操作
1 | fail?fail(CTResponse):nil |
6. 封装一个统一的空值处理
1 | #import "NSObject+AXNetworkingMethods.h" |
如果要是Swift的话其实就不用这么搞啦^_^
1 | optionalVarA ?? "为空的时候我就派上用场啦" |