最近公司的項目把網(wǎng)絡(luò)庫從ASIHTTPRequest 全部替換成了AFNetworking帘靡,但是在iOS 7上遇到了頻率很高的crash啊终。具體崩潰在AFURLSessionManager.h
里的[self.mutableData appendData:data];
這一行
- (void)URLSession:(__unused NSURLSession *)session
dataTask:(__unused NSURLSessionDataTask *)dataTask
didReceiveData:(NSData *)data
{
[self.mutableData appendData:data];
}
打印的log
malloc: *** error for object 0x633c000: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
意思應(yīng)該是mutableData
在某處被釋放了沦疾,于是查找所有用到mutableData
的地方
- (void)URLSession:(__unused NSURLSession *)session
task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error{
...
NSData *data = nil;
if (self.mutableData) {
data = [self.mutableData copy];
self.mutableData = nil;
}
...
}
在這個回調(diào)里mutableData
被釋放掉了绒怨,但是在iOS 7以上的系統(tǒng)卻沒發(fā)現(xiàn)崩潰,應(yīng)該是iOS 7里块攒,同一個task励稳,這兩個方法是在兩個線程異步執(zhí)行的,導(dǎo)致mutableData
提前置為nil囱井。
解決辦法
在操作mutableData
的地方加鎖麦锯,并且加了版本判斷,崩潰就基本不會復(fù)現(xiàn)了琅绅。
- (void)URLSession:(__unused NSURLSession *)session
dataTask:(__unused NSURLSessionDataTask *)dataTask
didReceiveData:(NSData *)data
{
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0) {
@synchronized (self.mutableData) {
if (!self.mutableData) {
self.mutableData = [NSMutableData data];
}
[self.mutableData appendData:data];
}
}else{
[self.mutableData appendData:data];
}
}
- (void)URLSession:(__unused NSURLSession *)session
task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error
{
...
NSData *data = nil;
if (self.mutableData) {
data = [self.mutableData copy];
//We no longer need the reference, so nil it out to gain back some memory.
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0) {//加鎖扶欣,防止崩潰在[self.mutableData appendData:data];
@synchronized (self.mutableData) {
self.mutableData = nil;
}
}else{
self.mutableData = nil;
}
}
...
}