這里我們只是向大家簡單介紹下AFNetWorking涉及到的知識點(diǎn),我們在之前以及之后的文章會詳細(xì)分析這些知識點(diǎn)。
一、Block的寫法。
詳細(xì)地址+Demo:http://www.itdecent.cn/p/73e8796942ec
二、FOUNDATION_EXPORT定義與#define定義的區(qū)別
#define kMyConstantString @"Hello"
//.h
FOUNDATION_EXPORT NSString * const AFNetworkingReachabilityDidChangeNotification;
FOUNDATION_EXPORT NSString * const AFNetworkingReachabilityNotificationStatusItem;
//.m
NSString * const AFNetworkingReachabilityDidChangeNotification = @"com.alamofire.networking.reachability.change";
NSString * const AFNetworkingReachabilityNotificationStatusItem = @"AFNetworkingReachabilityNotificationStatusItem";
-
FOUNDATION_EXPORT 與 #define 都可以用來定義常量
-
FOUNDATION_EXPORT定義的字符串直接比較的是指針地址
-
(#define)定義的字符串則是一一比較字符串的每一個(gè)字符是否相等
重點(diǎn):
1、FOUNDATION_EXPORT NSString * const定義的多個(gè)變量,不管它們的值相同或者不同,它們指針指向的內(nèi)存地址都相同。
2、#define定義的多個(gè)變量,如果變量值相同,那么內(nèi)存地址相同,值不同,內(nèi)存地址則不同。
為什么內(nèi)存地址會相同呢?
等找到原因了再補(bǔ)充下。
三、關(guān)于使用C語言寫私有方法
我個(gè)人的意見是一個(gè)類中的私有方法寫成static void funcName() 這樣的c函數(shù)比較好。
3.1. 在文件的最前方,比較容易查找
3.2. 可以適當(dāng)?shù)氖褂脙?nèi)聯(lián)函數(shù),提高效率。
四、AFSecurityPolicy
4.1. AFSSLPinningModeNone 代表無條件信任服務(wù)器的證書
4.2. AFSSLPinningModePublicKey 代表會對服務(wù)器返回的證書中的PublicKey進(jìn)行驗(yàn)證,通過則通過,否則不通過
4.3. AFSSLPinningModeCertificate 代表會對服務(wù)器返回的證書同本地證書全部進(jìn)行校驗(yàn),通過則通過,否則不通過
五、私有方法
開發(fā)中,使用私有化方法來協(xié)助我們達(dá)到某種目的或獲取某個(gè)數(shù)據(jù),且方法內(nèi)部沒有使用self,類似于這樣的方法,跟我們的業(yè)務(wù)并沒有太大的關(guān)系,此時(shí)我們可以使用static void這樣的私有化方法.
static void AFPostReachabilityStatusChange(SCNetworkReachabilityFlags flags, AFNetworkReachabilityStatusBlock block) {
AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags);
dispatch_async(dispatch_get_main_queue(), ^{
if (block) {
block(status);
}
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
NSDictionary *userInfo = @{ AFNetworkingReachabilityNotificationStatusItem: @(status) };
[notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:userInfo];
});
}
六、代碼思維碰撞
當(dāng)遇到比較復(fù)雜功能的時(shí)候,能不能寫出一個(gè)思路圖,先不管思路的實(shí)現(xiàn)如何,先一一列出來,最后再一一實(shí)現(xiàn),一一拼接起來。 沒有全局觀是不行的。
七、NSIndexSet
定義:NSIndexSet是一個(gè)有序的,唯一的,無符號整數(shù)的集合。
有序的輸出數(shù)據(jù),從小到大。
應(yīng)用場景:刪除表的區(qū)到就會用到indexset 來作為索引,才知道刪除第幾個(gè)區(qū)。
http://www.itdecent.cn/p/84a1d5296844
八、鎖
AFNetworking中我們總共見過三種鎖。
- synchronized 美 ['s??kr?na?zd]
- (BOOL)isNetworkActivityOccurring {
@synchronized(self) {
return self.activityCount > 0;
}
}
- dispatch_semaphore_wait 美 ['s?m?f?r] 信號量
- (NSArray *)tasksForKeyPath:(NSString *)keyPath {
__block NSArray *tasks = nil;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
if ([keyPath isEqualToString:NSStringFromSelector(@selector(dataTasks))]) {
tasks = dataTasks;
} else if ([keyPath isEqualToString:NSStringFromSelector(@selector(uploadTasks))]) {
tasks = uploadTasks;
} else if ([keyPath isEqualToString:NSStringFromSelector(@selector(downloadTasks))]) {
tasks = downloadTasks;
} else if ([keyPath isEqualToString:NSStringFromSelector(@selector(tasks))]) {
tasks = [@[dataTasks, uploadTasks, downloadTasks] valueForKeyPath:@"@unionOfArrays.self"];
}
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
return tasks;
}
- NSLock
+ (UIImage *)af_safeImageWithData:(NSData *)data {
UIImage* image = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
imageLock = [[NSLock alloc] init];
});
[imageLock lock];
image = [UIImage imageWithData:data];
[imageLock unlock];
return image;
}
九、NSURLCache
NSURLCache為應(yīng)用的URL提供了內(nèi)摧毀總以及磁盤上的綜合緩存機(jī)制。網(wǎng)絡(luò)緩存減少了向服務(wù)器發(fā)送請求的次數(shù),通知也提升了離線或在低速網(wǎng)路中使用應(yīng)用的體驗(yàn)。當(dāng)一個(gè)請求完成了來自服務(wù)器的回應(yīng),回應(yīng)將會在本地保存。下一次同一個(gè)請求再發(fā)起時(shí),本地保存的回一個(gè)就會馬上返回,不需要鏈接服務(wù)器。
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024
diskCapacity:20 * 1024 * 1024
diskPath:nil];
[NSURLCache setSharedURLCache:URLCache];
}
URLRequest 有個(gè) cachePolicy 屬性,我們平時(shí)最常用的有四個(gè)屬性:
- NSNSURLRequestUseProtocolCachePolicy: 對特定的 URL 請求使用網(wǎng)絡(luò)協(xié)議中實(shí)現(xiàn)的緩存邏輯。這是默認(rèn)的策略
- NSURLRequestReloadIgnoringLocalCacheData:數(shù)據(jù)需要從原始地址加載。不使用現(xiàn)有緩存。
- NSURLRequestReturnCacheDataElseLoad:無論緩存是否過期,先使用本地緩存數(shù)據(jù)。如果緩存中沒有請求所對應(yīng)的數(shù)據(jù),那么從原始地址加載數(shù)據(jù)
- NSURLRequestReturnCacheDataDontLoad:無論緩存是否過期,先使用本地緩存數(shù)據(jù)。如果緩存中沒有請求所對應(yīng)的數(shù)據(jù),那么放棄從原始地址加載數(shù)據(jù),請求視為失?。矗骸半x線”模式)。
十、內(nèi)聯(lián)函數(shù)(inline)
我們在AFNetWorking中經(jīng)常見到inline(內(nèi)聯(lián)函數(shù)),心里多多少少會犯嘀咕,這是什么函數(shù)?有什么用?用了有什么好處?什么時(shí)候用?
static inline NSString * AFContentTypeForPathExtension(NSString *extension) {
#ifdef __UTTYPE__
NSString *UTI = (__bridge_transfer NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)extension, NULL);
NSString *contentType = (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)UTI, kUTTagClassMIMEType);
if (!contentType) {
return @"application/octet-stream";
} else {
return contentType;
}
#else
return @"application/octet-stream";
#endif
}
- 什么是內(nèi)聯(lián)函數(shù)(inline)
定義:內(nèi)聯(lián)函數(shù)是指用inline關(guān)鍵字修飾的函數(shù)。在類內(nèi)定義的函數(shù)被默認(rèn)成內(nèi)聯(lián)函數(shù)。 當(dāng)編譯器發(fā)現(xiàn)某段代碼在調(diào)用一個(gè)內(nèi)聯(lián)函數(shù)時(shí),它不是去調(diào)用該函數(shù),而是將該函數(shù)的代碼整段插入到當(dāng)前位置。這樣做的好處是省去了調(diào)用的過程,加快了程序運(yùn)行速度。(函數(shù)的調(diào)用過程,由于有前面所說的參數(shù)入棧等操作,所以總要多占用一些時(shí)間)
壞處:由于每當(dāng)代碼調(diào)用到內(nèi)聯(lián)函數(shù),就需要在調(diào)用處直接插入一段該函數(shù)的代碼,所以程序的體積將增大。
內(nèi)聯(lián)函數(shù)的本質(zhì)是:節(jié)省時(shí)間但是消耗空間。
這么說吧,就是我們早期抗戰(zhàn)的原則:拿空間換時(shí)間。
- 內(nèi)聯(lián)函數(shù)調(diào)用效率
1、函數(shù)之間的調(diào)用是內(nèi)存地址之間的調(diào)用,當(dāng)函數(shù)調(diào)用完畢之后,還會返回原來函數(shù)執(zhí)行的地址。函數(shù)調(diào)用有時(shí)間開銷,內(nèi)聯(lián)函數(shù)就是為了解決這個(gè)問題。
2、不用inline修飾的函數(shù),匯編時(shí)會調(diào)用call指令:
. call指令是計(jì)算機(jī)轉(zhuǎn)移到調(diào)用的子程序,兩步操作:
(1)將程序下一條指令的位置的IP壓入堆棧中;
(2)轉(zhuǎn)移到調(diào)用的子程序。
- 內(nèi)聯(lián)函數(shù)使用規(guī)則
1、一個(gè)函數(shù)可以自己調(diào)用自已,稱為遞歸調(diào)用(后面講到),含有遞歸調(diào)用的函數(shù)不能設(shè)置為inline;
2、使用了復(fù)雜流程控制語句:循環(huán)語句和switch語句,無法設(shè)置為inline;(這一點(diǎn)存疑,AFNetWorking里面有使用switch的內(nèi)聯(lián)函數(shù))
static inline NSString * AFKeyPathFromOperationState(AFOperationState state) {
switch (state) {
case AFOperationReadyState:
return @"isReady";
case AFOperationExecutingState:
return @"isExecuting";
case AFOperationFinishedState:
return @"isFinished";
case AFOperationPausedState:
return @"isPaused";
default:
return @"state";
}
}
3、由于inline增加體積的特性,所以建議inline函數(shù)內(nèi)的代碼應(yīng)該很短小。
4、inline僅作為一種“請求”,特定情況下編譯器將不會理會inline關(guān)鍵字,而強(qiáng)制讓函數(shù)稱為普通函數(shù),這樣編譯器會輸出警告信息。
5、在盜用一個(gè)內(nèi)聯(lián)函數(shù)之前,一定要在函數(shù)之前定義或聲明inline,如果在前面聲明為普通函數(shù),而在調(diào)用代碼后面才定義為一個(gè)inline函數(shù),程序可以通過編譯,但該函數(shù)沒有實(shí)現(xiàn)inline。
內(nèi)聯(lián)函數(shù)相較于函數(shù)的優(yōu)點(diǎn)
1、inline函數(shù)避免了普通函數(shù)的,在匯編時(shí)必須調(diào)用call的缺點(diǎn):取消了函數(shù)的參數(shù)壓棧,減少了調(diào)用的開銷,提高效率.所以執(zhí)行速度確比一般函數(shù)的執(zhí)行速度要快.
2、集成了宏的優(yōu)點(diǎn),使用時(shí)直接用代碼替換(像宏一樣);內(nèi)聯(lián)函數(shù)相較于宏的優(yōu)點(diǎn)
1、避免的宏的缺點(diǎn),宏需要編譯,inline不需要編譯,內(nèi)聯(lián)函數(shù)也是函數(shù),不需要編譯。
2、編譯器在調(diào)用一個(gè)內(nèi)聯(lián)函數(shù)時(shí),會首先檢查它參數(shù)的類型,保證調(diào)用的正確。然后進(jìn)行一系列的相關(guān)檢查,就像對待一個(gè)真正的函數(shù)一樣。這就消除的了隱患和局限性。
3、可以使用所在類的保護(hù)成員以及私有成員。