使用此处的函数从异步块返回值(只是数据库查询)。问题是应用程序冻结并因内存问题而终止。寻求建议是否最好在主线程上运行它还是应该避免这种情况?请注意,它正在另一个线程上执行。
- (NSString *)databaseQuery:(NSString*)ingredient {
__block NSString *valueType = nil;
__block BOOL done = NO;
[[[_ref child:@"ingredients"] queryEqualToValue:valueType childKey:ingredient] observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
for (FIRDataSnapshot *child in snapshot.children) {
valueType = child.value;
}
done = YES;
} withCancelBlock:^(NSError * _Nonnull error) {
NSLog(@"%@", error.localizedDescription);
done = YES;
}];
while (!done) {
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
}
return valueType;
}
更新1:尝试使用以下代码并产生相同的结果。
- (NSString *)databaseQuery:(NSString*)ingredient {
__block NSString *valueType = nil;
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
FIRDatabaseQuery *query = [[_ref child:@"ingredients"] queryEqualToValue:valueType childKey:ingredient] ;
[query observeEventType:FIRDataEventTypeChildAdded
withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
valueType = snapshot.value;
dispatch_semaphore_signal(sem);
}
withCancelBlock:^(NSError * _Nonnull error) {
NSLog(@"%@", error.localizedDescription);
dispatch_semaphore_signal(sem);
}];
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
return valueType;
}
更新2:
更改了格式,因此函数不会从块返回。它只返回FIRDatabaseQuery。
- (FIRDatabaseQuery *)databaseQuery:(NSString*)ingredient {
__block NSString *valueType = nil;
FIRDatabaseQuery *query = [[_ref child:@"ingredients"] queryEqualToValue:valueType childKey:ingredient];
return query;
}
以下部分是另一个程序。除了返回的值为null。
query = [self databaseQuery:substring];
[query observeEventType:FIRDataEventTypeChildAdded
withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
idValue = snapshot.value;
}
withCancelBlock:^(NSError * _Nonnull error) {
NSLog(@"%@", error.localizedDescription);
}];
NSLog(@"%@", idValue);
答案 0 :(得分:0)
解决:尽管我想避免使用NSRunLoop,但问题是我已经运行了一个并且我没有停止它。
答案是将CFRunLoopStop(CFRunLoopGetCurrent());
添加到应用程序中。应该使用信号量替换它。
问题是,这是一个循环。搜索完第一个项目后,它会卡住并再次挂起。为了解决这个问题,我按照建议使用了调度组。
注意:在循环之前声明调度组以及idValue。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_group_enter(_groupSearch);
dispatch_async(queue, ^{
[[self databaseQuery:searchItem] observeEventType:FIRDataEventTypeChildAdded
withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
idValue = snapshot.value;
dispatch_group_leave(_groupSearch);
}
withCancelBlock:^(NSError * _Nonnull error) {
NSLog(@"%@", error.localizedDescription);
dispatch_group_leave(_groupSearch);
}];
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_group_wait(_groupSearch, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)));
dispatch_sync(queue, ^{
if (idValue != NULL) {
NSLog(@"%@",idValue);
}
});
});