0

在CoreDataTableViewController(由斯坦福大學人員完成的子類)上,我從sqlite數據庫獲取數據。後臺線程的行爲有所不同,具體取決於其調用方法

在模擬器和設備上抓取速度非常快,但爲了使它更老 - 設備友好,我想在背景上執行抓取並在完成時添加微調器。所以我添加了一個預取方法。整個事情是這樣的:

-(void)setupFetchedResultsController{ 

    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:self.entity]; 

    request.propertiesToFetch=[NSArray arrayWithObject:self.attribute]; 
    request.resultType=NSDictionaryResultType; 
    request.returnsDistinctResults=YES; 

    NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"%K != nil", self.attribute]; 
    NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"%K != ''", self.attribute]; 
    NSPredicate *predicate3= [NSPredicate predicateWithFormat:@"%K contains[cd] %@", self.attribute, self.seachBar.text]; 

    NSArray *prepredicateArray; 

    if ([self.seachBar.text length]) { 
     prepredicateArray = [NSArray arrayWithObjects:predicate1, predicate2, predicate3,nil]; 

    }else { 
     prepredicateArray = [NSArray arrayWithObjects:predicate1, predicate2,nil]; 

    } 

    request.predicate=[NSCompoundPredicate andPredicateWithSubpredicates:prepredicateArray]; 
    request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:self.attribute ascending:YES ]]; 


    self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request 
                     managedObjectContext:self.managedObjectContext 
                      sectionNameKeyPath:nil 
                        cacheName:nil]; 


    [self performFetch]; 
} 





-(void)prefetch{ 

    UIView *translucentView=[[UIView alloc]initWithFrame:CGRectMake(110, 102, 100, 100)]; 
    [translucentView setCornerRadius:7.0]; 
    translucentView.backgroundColor=[UIColor blackColor]; 
    translucentView.alpha=0.65; 

    UIActivityIndicatorView *spinner=[[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; 
    spinner.frame=CGRectMake(0, 31.5, 100, 37); 
    [translucentView addSubview:spinner]; 

    [spinner startAnimating]; 

    [self.view addSubview:translucentView]; 


    dispatch_queue_t fetchQueue = dispatch_queue_create("fetch stuff", NULL); 

    dispatch_async(fetchQueue, ^{ 

     [self setupFetchedResultsController]; 

     dispatch_async(dispatch_get_main_queue(), ^{ 

      [translucentView removeFromSuperview]; 

     }); 

    }); 

    dispatch_release(fetchQueue); 

} 

的事情是,當我稱之爲prefetch方法從viewWillAppear一切都很好,但是當我把它從一個編輯搜索欄時調用的方法(抓取動態顯示牽強結果,而輸入一個搜索欄),它提供了以下錯誤:

void _WebThreadLockFromAnyThread(bool), 0x6b9b730: Obtaining the web lock from a thread other than the main thread or the web thread. UIKit should not be called from a secondary thread. 

這是我的理解是UI的東西應該在主線程上執行,但是我看不出哪裏出錯。

任何指針?提前致謝!

+0

我給這個問題添加了一個ios標籤。不知道這是否正確。 – Gray

+0

您是否真的在舊設備上測試過性能?核心數據的抓取速度非常快,您可以設置抓取請求來限制返回的記錄數,錯誤選項等,這樣會有所幫助。另外,不太確定在後臺線程上創建'NSFetchedResultsController'是個好主意。您是否閱讀過關於核心數據和併發性的Apple文檔?如果你繼續沿着這條路走下去(你應該只用核心數據做最後的手段),那將是有幫助的, – gschandler

+0

是的,我認爲你是可行的。我剛剛重新看了斯坦福大學課程的第14課,在第一張幻燈片中講師說:核心數據不是線程安全的。所以,問題一定是在這裏。人們可以在一個塊上執行它。但正如你所指出的那樣,甚至可能沒有必要。剩下的感謝。 – Marcal

回答

1

我認爲這可能是由於訪問搜索欄的文本引起的。我在後臺線程方法中遇到了類似的警告,並將問題追蹤到搜索欄的文本方法。我注意到你也在這樣做。

如果這是您的情況,警告的簡單解決方案是在主線程中獲取搜索欄的文本。

它確實解決了我的問題,但我真的想知道爲什麼警告顯示。我一直試圖在網絡和Apple的文檔中找到一些關於這方面的內容,但還沒有運氣。

+0

感謝您的回答。下次處理問題時我會看看(更新已在商店中)。但是,我深入研究了關於核心數據的文檔,它確實不是線程安全的,所以必須小心謹慎。我相信一個官方的工作是在一個塊內執行取指操作。 – Marcal

+0

由於核心數據不是線程安全的,因此警告不出現。在後臺線程中使用塊不會刪除警告,因爲它仍將在後臺完成。 – Sebastian

+0

核心數據不是線程安全的,意味着併發執行可能會導致不可預知的結果。如果您從後臺線程(我相信是搜索欄的文本,正如我指出的那樣)中刪除正在訪問UI界面的任何內容,您仍然可以在沒有該警告的情況下在後臺執行此操作。但有一種方法可以確保永遠不會有多個執行核心數據邏輯的線程,以防止出現不可預知的結果。 – Sebastian

相關問題