之前在調(diào)試跨層傳值的問題時(shí)發(fā)現(xiàn)一個(gè)很奇怪的問題:請求數(shù)據(jù)完成后的block會回調(diào)兩次。苦思冥想了好久都沒有理解為什么。C控制器中block回調(diào)中的代理方法會調(diào)用B控制器中的代理方法,B控制器中的代理方法會調(diào)用A控制器中的代理方法。
這是在C控制器
[XJHttpTool PUT:url dictParameters:params success:^(id responseObject) {
if ([[responseObject objectForKey:@"success"] integerValue]==1) {
NSDictionary *dic = [responseObject objectForKey:@"kanban"];
BoardModel *boardModle =[BoardModel objectWithKeyValues:dic];
if ([self.delegate respondsToSelector:@selector(didChangeBoardInfo:andChangedStar:)]) {
[self.delegate didChangeBoardInfo:boardModle andChangedStar:self.changedStar];
}
}else{
[self alertUserWrongInfo:@"保存失敗!"];
}
} failure:^(NSError *error) {
[self alertUserWrongInfo:@"保存失敗!"];
}];
直到今天早上再次調(diào)試的時(shí)候,發(fā)現(xiàn)控制臺輸出了這個(gè)信息:
'NSGenericException', reason: '*** Collection <__NSArrayM: 0x8ef350> was mutated while being enumerated.')
然后我就明白了。這個(gè)錯(cuò)誤的意思是如果對數(shù)組枚舉的時(shí)候不能同時(shí)對其進(jìn)行元素的刪除操作。
這是在上文block回調(diào)后A控制器中調(diào)用的代理方法
for (NSArray *arr in self.boardArrayM) {
if (arr.count == 0) {
[self.boardArrayM removeObject:arr];
}
}
解決方法1:定義一個(gè)一模一樣的數(shù)組,遍歷數(shù)組A然后操作數(shù)組B。
NSMutableArray *arrM = [NSMutableArray arrayWithArray:self.boardArrayM];
for (NSArray *arr in arrM) {
if (arr.count == 0) {
[self.boardArrayM removeObject:arr];
}
}
解決方法2:使用for(;;)循環(huán)。而不是for in枚舉遍歷。
解決了這個(gè)問題后,我發(fā)現(xiàn)block的回調(diào)正常了,只調(diào)用一次。雖然我不明白為什么多個(gè)線程操作同一個(gè)數(shù)組引起問題與這個(gè)有什么聯(lián)系(是線程調(diào)度紊亂?),但問題確實(shí)是解決了。如果有明白的希望能留言告訴我,謝謝!
而且dealloc測試后發(fā)現(xiàn)沒有修改前,頁面跳轉(zhuǎn)到B控制器中時(shí),C控制器是沒有銷毀的,頁面跳轉(zhuǎn)到A控制器時(shí),C控制器也沒有銷毀,所以C中的方法可以再次被線程調(diào)用(怎么就調(diào)用了?不懂,有大牛請指點(diǎn)!),按理說導(dǎo)航控制器的子控制器出棧時(shí)應(yīng)當(dāng)銷毀的,而在做了修改后,頁面跳轉(zhuǎn)到B控制器時(shí),C控制器是銷毀的,這個(gè)是正常的,銷毀了當(dāng)然方法就不可能會被再次調(diào)用了。