gpt4 book ai didi

ios - 使用循环运行后台获取时出现 NSInternalInconsistencyException

转载 作者:塔克拉玛干 更新时间:2023-11-02 09:26:07 24 4
gpt4 key购买 nike

我有这段代码试图在后台获取 HealthKit 数据。当我第一次运行该应用程序时,代码运行良好,但如果我手动执行后台提取(使用调试命令),我会抛出一个异常并显示一个错误,内容为 reason: 'this request has been neutered - you can 't call -sendResponse: twice or after encoding it' 我不太清楚为什么。

这是获取数据的代码:

- (void)fetchNewDataWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {

if (!self.healthStore) {
self.healthStore = [HKHealthStore new];
}

dataTypes = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:1], HKQuantityTypeIdentifierStepCount,
[NSNumber numberWithInt:2], HKQuantityTypeIdentifierFlightsClimbed,
[NSNumber numberWithInt:3], HKQuantityTypeIdentifierDistanceWalkingRunning,
[NSNumber numberWithInt:4], HKQuantityTypeIdentifierDistanceCycling, nil];
achievementData = [NSMutableDictionary new];

NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *startDate = [calendar startOfDayForDate:[NSDate date]];
NSDate *endDate = [calendar dateByAddingUnit:NSCalendarUnitDay value:1 toDate:startDate options:0];
NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionNone];

for (NSString *key in dataTypes) {

HKSampleType *sampleType = [HKSampleType quantityTypeForIdentifier:key];

HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:sampleType predicate:predicate limit:HKObjectQueryNoLimit sortDescriptors:nil resultsHandler:^(HKSampleQuery *query, NSArray *results, NSError *error) {

if (!error) {

if (!results) {

NSLog(@"No results were returned form query");

completionHandler(UIBackgroundFetchResultNoData);

} else {

dispatch_async(dispatch_get_main_queue(), ^{

[self processNewDataWithResults:results andType:key];

completionHandler(UIBackgroundFetchResultNewData);

});

}

} else {

NSLog(@"Error: %@ %@", error, [error userInfo]);

completionHandler(UIBackgroundFetchResultFailed);

}

}];

[self.healthStore executeQuery:query];

}

}

然后我有一个单独的函数来处理您可以看到的数据,当找到结果时会调用该函数。如果你愿意,我可以把它贴在这里,但它很长,不确定它是否与它有任何关系。

我尝试放置断点以查看何时调用完成处理程序,但据我所知它只被调用一次,除非我在这里遗漏了一些愚蠢的东西。

如果有人有任何建议,请告诉我:) 谢谢!

编辑错误消息如下所示:

2015-05-13 10:11:54.467 appName[379:169163] *** Assertion failure in -[UIFetchContentInBackgroundAction sendResponse:], /SourceCache/BaseBoard/BaseBoard-98.3/BaseBoard/BSAction.m:221
2015-05-13 10:11:54.470 appName[379:169163] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'this request has been neutered - you can't call -sendResponse: twice nor after encoding it'
*** First throw call stack:
(0x28ed4137 0x36e30c77 0x28ed400d 0x29bd2bc9 0x2dbde865 0x397ed5 0x2dbde7cf 0x2ca82a3d 0x39019b 0x390187 0x393e9d 0x28e99889 0x28e97fa9 0x28de39a1 0x28de37b3 0x305951a9 0x2c56e695 0xdff29 0x373d8aaf)
libc++abi.dylib: terminating with uncaught exception of type NSException

最佳答案

通过查看您发布的代码,除了由于 for 循环,后台获取完成处理程序将被恰好调用 4 次之外,我没有看到任何其他方式。

HKSampleQuery 的每个实例的 resultHandlers 中的代码路径将以 completionHandler(UIBackgroundFetchResult...) 调用结束case 并且您总是实例化其中的四个,所以这就是断言 'you can't call -sendResponse: twice' 对 IMO 的提示。

通过注释掉 dataTypes 字典中的 3 个查询,应该很容易检查这是否是问题所在。

编辑:根据评论中的要求,这里有一个可能的解决方案(..就在我的脑海中,所以要半信半疑..):

它 (a) 使用信号量锁将异步查询结果回调转换为“同步”调用 & (b) 在执行完成处理程序之前使用调度组等待所有 4 个查询完成。

// NOTE: This example assumes that the fetch has "new data" if any of the queries returned something
// Also it skips the 'NSError' part (which could work exactly like the 'result' var)

// Define one or more block-global result variables for queries can put their end state into
UIBackgroundFetchResult __block result = UIBackgroundFetchResultNoData;

// Create a dispatch group that will manage all the concurrent queries
dispatch_queue_t queue = dispatch_queue_create([@"my.query.queue" UTF8String], DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t queries = dispatch_group_create();

// For each dataType dispatch a group block containing the query to run on the concurrent queue
for (NSString *key in dataTypes) {
dispatch_group_async(queries, queue, ^{
// To work around the asynchronous callback, I'll use a lock to wait for the query to return their result, so..

// ..like above, a block-global var will hold the result of the query
BOOL __block success = NO;

// ..create a one-time lock..
dispatch_semaphore_t lock = dispatch_semaphore_create(0);
HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:sampleType predicate:predicate limit:HKObjectQueryNoLimit sortDescriptors:nil resultsHandler:^(HKSampleQuery *query, NSArray *results, NSError *error) {
success = YES; // ..or however you define success.. ;)

dispatch_semaphore_signal(lock); // ..open lock to signal result available..
}];
dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER); // ..wait for callback result lock to open..

// ..determine & set result.
if (success) {
result = UIBackgroundFetchResultNewData;
}
});
}

// Schedule a final block to execute (on the main queue) when all the other group blocks have finished running
dispatch_group_notify(queries, dispatch_get_main_queue(), ^{
// Determine final result and call completion handler
completionHandler(result);
});

关于ios - 使用循环运行后台获取时出现 NSInternalInconsistencyException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30217315/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com