之前在调试跨层传值的问题时发现一个很奇怪的问题:请求数据完成后的block会回调两次。苦思冥想了好久都没有理解为什么。C控制器中block回调中的代理方法会调用B控制器中的代理方法,B控制器中的代理方法会调用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:@"保存失败!"];
}];
直到今天早上再次调试的时候,发现控制台输出了这个信息:
'NSGenericException', reason: '*** Collection <__NSArrayM: 0x8ef350> was mutated while being enumerated.')
然后我就明白了。这个错误的意思是如果对数组枚举的时候不能同时对其进行元素的删除操作。
这是在上文block回调后A控制器中调用的代理方法
for (NSArray *arr in self.boardArrayM) {
if (arr.count == 0) {
[self.boardArrayM removeObject:arr];
}
}
解决方法1:定义一个一模一样的数组,遍历数组A然后操作数组B。
NSMutableArray *arrM = [NSMutableArray arrayWithArray:self.boardArrayM];
for (NSArray *arr in arrM) {
if (arr.count == 0) {
[self.boardArrayM removeObject:arr];
}
}
解决方法2:使用for(;;)循环。而不是for in枚举遍历。
解决了这个问题后,我发现block的回调正常了,只调用一次。虽然我不明白为什么多个线程操作同一个数组引起问题与这个有什么联系(是线程调度紊乱?),但问题确实是解决了。如果有明白的希望能留言告诉我,谢谢!
而且dealloc测试后发现没有修改前,页面跳转到B控制器中时,C控制器是没有销毁的,页面跳转到A控制器时,C控制器也没有销毁,所以C中的方法可以再次被线程调用(怎么就调用了?不懂,有大牛请指点!),按理说导航控制器的子控制器出栈时应当销毁的,而在做了修改后,页面跳转到B控制器时,C控制器是销毁的,这个是正常的,销毁了当然方法就不可能会被再次调用了。
网友评论