如何解决 dispatch_group_leave 崩溃

How to troubleshoot a dispatch_group_leave crash

我知道 dispatch_group_leave 调用需要与 dispatch_group_enter 平衡。 这是发生崩溃的代码块(随机发生,并非总是如此)

            dispatch_group_t group = dispatch_group_create();
            dispatch_group_enter(group);
            [self getVibrationHistorySuccess:^(NSArray<VibrationPointDTO *> *vibrationPoints) {
                self.vibrationPoints = vibrationPoints;
                dispatch_group_leave(group);
            } failure:^(NSError *error) {
                dispatch_group_leave(group);
            }];

            dispatch_group_enter(group);
            [self getTemperatureHistorySuccess:^(NSArray<TemperatureSetDTO *> *sets) {
                self.temperatureSets = sets;
                dispatch_group_leave(group);
            } failure:^(NSError *error) {
                dispatch_group_leave(group);
            }];

            dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
                [self showLoading:NO];
                [self updateChartWithVibrationHistory:self.vibrationPoints temperatureSets:self.temperatureSets];
            });

有 2 次进入和 2 次退出(在每个闭包上,只有成功或失败的可能,所以只有这 2 次发生之一)

那么为什么我的代码会像这样崩溃?我该如何解决这个问题?

我唯一想到的另一件事是,该对象的多个实例确实同时被使用。这些不同的实例是否可能正在使用同一个组?是否有办法确保组本身在这些实例之间是唯一的?否则我想不出为什么会这样。

PS:我还添加了 swift 标签,以便更多地关注这个问题,因为无论使用何种语言,同样的问题都可能发生

编辑 1

根据收到的评论添加缺失的方法:

这是 getTemperatureHistorySuccess 崩溃的

-(void)getTemperatureHistorySuccess:(void (^)(NSArray<TemperatureSetDTO*> *sets))success
                            failure:(void(^)(NSError *error))failure{
    NSMutableArray *sets = [NSMutableArray new];
    dispatch_group_t group = dispatch_group_create();

    for (TemperatureSummaryNew *sensor in self.regionPCA.temperatureSensors) {
        dispatch_group_enter(group);
        [TemperatureSensorsService getHistory:sensor.temperatureSensorID startDate:self.startDate stopDate:self.stopDate interval:self.currentInterval success:^(NSArray<TemperaturePointDTO *> *result) {
            TemperatureSetDTO *set = [TemperatureSetDTO new];
            set.points = result;
            [sets addObject:set];
            dispatch_group_leave(group);
        } failure:^(NSError *error) {
            dispatch_group_leave(group);
        }];
    }

    dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
        success(sets);
    });
}

这是在循环中调用的 getHistory

+ (void) getHistory:(int)sensorID
          startDate:(NSDate*)startDate
           stopDate:(NSDate*)stopDate
           interval:(HistoryInterval)interval
            success:(void (^)(NSArray<TemperaturePointDTO*>* result))success
            failure:(void(^)(NSError *error))failure{
    ApiManager *api = [ApiManager sharedManager];

    NSDictionary *params = @{
                             @"TemperatureSensorID" : [Converter toDictionaryValueFromInt:sensorID],
                             @"StartDate" : [Converter toDictionaryValueGMTFromDate:startDate],
                             @"StopDate" : [Converter toDictionaryValueGMTFromDate:stopDate],
                             @"Interval" : [Converter toDictionaryValueFromHistoryInterval:interval]};
    [api POST:kApiTemperatureSensorsGetHistory parameters:params progress:nil success:^(NSURLSessionDataTask *task, id responseObject) {
        if (success) {
            NSArray*  res = [Converter fromDictionaryValueToTemperaturePointDTOArray:responseObject];
            success(res);
        }
    } failure:^(NSURLSessionDataTask *task, NSError *error) {
        if (failure) {
            failure(error);
        }
    }];
}

这里是getVibrationHistorySuccess

-(void)getVibrationHistorySuccess:(void (^)(NSArray<VibrationPointDTO *> *vibrationPoints))success
          failure:(void(^)(NSError *error))failure{
    __block NSArray<VibrationPointDTO *> *points;
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_enter(group);
    [self getDistanceHistorySuccess:^{
        dispatch_group_leave(group);
    } failure:^(NSError *error) {
        dispatch_group_leave(group);
    }];
    dispatch_group_enter(group);
    [VibrationSensorsService getHistory:self.regionPCA.regionID startDate:self.startDate stopDate:self.stopDate interval:self.currentInterval success:^(NSArray<VibrationPointDTO *> *result) {
        points = result;
        dispatch_group_leave(group);
    } failure:^(NSError *error) {
        dispatch_group_leave(group);
        failure(error);
    }];
    dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
        success(points);
    });
}

VibrationSensorsService getHistory与上一个完全一样,只是指向不同的端点

这是从您的问题中复制的 getVibrationHistorySuccess:failure: 的最后一部分:

[VibrationSensorsService getHistory:self.regionPCA.regionID startDate:self.startDate stopDate:self.stopDate interval:self.currentInterval success:^(NSArray<VibrationPointDTO *> *result) {
    points = result;
    dispatch_group_leave(group);
} failure:^(NSError *error) {
    dispatch_group_leave(group);
    failure(error);
}];
dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
    success(points);
});

此代码总是 调用success(points)。此外,它 有时 调用 failure(error)。这意味着 successfailure 块都可以执行。