2017-09-10 158 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); 
         } 
        }); 
       });