2017-09-10 117 views
0

使用此处的函数从异步块返回值(仅数据库查询)。问题是由于内存问题,应用程序冻结并终止。寻求建议是否最好在主线上运行它,还是应该避免这种情况?注意它正在另一个线程上执行。异步块返回问题

- (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; 
} 

UPDATE 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; 
} 

下面的部分是在另一个过程中。除了返回的值为空。

query = [self databaseQuery:substring]; 
      [query observeEventType:FIRDataEventTypeChildAdded 
          withBlock:^(FIRDataSnapshot * _Nonnull snapshot) { 
           idValue = snapshot.value; 
          } 
        withCancelBlock:^(NSError * _Nonnull error) { 
         NSLog(@"%@", error.localizedDescription); 
        }]; 
      NSLog(@"%@", idValue); 
+0

你能给出关于内存问题的更多细节吗?哪条线/你有什么例外? 并且您是否尝试使用'dispatch_group_t'而不是在while循环内运行'NSRunLoop'? –

+0

我可以尝试使用派遣组t。内存不是问题,只是应用程序的结果被卡在线程中。 –

+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); 
         } 
        }); 
       });