记录一个遇到的iOS多线程闪退

遇到一个闪退,在开发的时候,遇到过,但是很难复现,但是偶尔还是会有出现的,就是这样一个问题

NSArrayM: 0xb550c30> was mutated while being enumerated

这段报错,看起来是一个正在遍历一个数组的时候,我们修改了它导致的,但是我们的代码中并没有在一个for 循环中或者 enumerate中去改变一个数组的操作,后来推测,
有可能是一个数组在被遍历的时候,被其他线程修改了,导致的这个问题。
后来排查代码,确实是这个问题,
下面贴出代码,方便大家借鉴

获取数据的方法

- (NSDictionary *)getMergedDataWithKeys:(NSArray *)keys {
    NSMutableDictionary *getData = [[NSMutableDictionary alloc] init];
    
    for (NSString *key in keys) {
        for (NSDictionary *tosynchronizedData in self.DataList) {
            NSString *tosynchronizedIDString = [tosynchronizedData objectForKey:@"id"];
            
            if (![key isEqualToString:tosynchronizedIDString]) continue;
            
            [getData addEntriesFromDictionary:[tosynchronizedData objectForKey:@"data"]];
            
            break;
        }
    }
    
    return getSynchronizedData;
}

崩溃就是崩溃在上面这段循环遍历的代码中了
但是问题出在我们其他的放的调用上,

更新数据的方法

- (void)updateDic:(NSArray *)newData {
    NSMutableArray *keysToUpdate = [[NSMutableArray alloc] init];
    
    for (NSDictionary *data in newData) {
        NSString *IDString = [data stringForKey:@"id"];
        NSString *type = [data stringForKey:@"type" "];
        NSDictionary *tmpData = [data dictionaryForKey:@"data"];
        
        if (IDString.length <= 0 || type.length <= 0 || tmpData.count <= 0) continue;
        
        NSUInteger synchronizedTemplateDataToUpdateIndex = 0;
        NSDictionary *synchronizedTemplateDataToUpdate = nil;
        
        for (NSUInteger i = 0; i < self.synchronizedDataList.count; i++) {
            NSDictionary *synchronizedData = [self.synchronizedDataList objectOrNilAtIndex:i];
            NSString *synchronizedIDString = [synchronizedData stringForKey_ap:@"id" defaultValue:@""];
            NSString *synchronizedType = [synchronizedData stringForKey_ap:@"type" defaultValue:@""];
            NSMutableDictionary *synchronizedTemplateData = [[synchronizedData dictionaryForKey_ap:@"data"] mutableCopy];
            
            if (![synchronizedIDString isEqualToString:IDString] || ![synchronizedType isEqualToString:type]) continue;
            
            for (NSString *key in tmpData.allKeys) {
                NSString *value = [tmpData stringForKey:key];
                
                [synchronizedTemplateData setObject:value forKey:key];
            }
            
            synchronizedTmpDataToUpdateIndex = i;
            synchronizedTmpDataToUpdate = @{
                @"id": IDString,
                @"type": type,
                @"data": synchronizedTemplateData
            };
            
            break;
        }
        
        if (synchronizedTemplateDataToUpdate == nil) {
            [self.DataList addObject:data];
        } else {
            [self.DataList removeObjectAtIndex:synchronizedTemplateDataToUpdateIndex];
            [self.DataList addObject:synchronizedTemplateDataToUpdate];
        }
        
        [keysToUpdate addObjectOrNil:@{
            @"id": IDString ?: @"",
            @"type": type ?: @""
        }];
    }
}

调用的地方,
其他地方都是主线程在掉用,获取也是在主线程,
但是新写了一个调用修改数据的地方,在自线程

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
updateDic
});

修复

    dispatch_async(dispatch_get_main_queue(), ^{
updateDic
});
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值