7

我在iOS Core Data數據庫中有一組實體對象,用於描述某個位置的某些內容。我們調用實體位置。我已經通過在位置上引用了兩個屬性來實現這一點,即位置 - 緯度和經度,兩者都是雙倍。還有其他元素,比如名字。核心數據中的位置通過NSFetchedResultsController按距離排序?

我正在使用NSFetchedResultsController將實體綁定到UITableViewController。我想要做的是將結果按照給定CLLocationCoordinate2D的距離排序。在一個非常理想的情況下,我可以刷新該列表以重新計算基於新位置的排序。因此,這種排序取決於兩個鍵和第三個「靜態」變量(不同於集合中的項目)。

我想我可以弄清楚如何使用NSSortDescriptors排序任意列表。但是,我不控制如何在NSFetchedResultsController中使用排序描述符。

有沒有一種方法可以配置我的實體,我的NSFetchedResultsController,我的NSSortDescriptors等來完成此操作?我懷疑答案不在於創建花哨的NSSortDescriptor,而是在代表距離的實體中創建瞬態屬性,並定期重新計算該屬性。然而,我已經足夠新的核心數據,我不知道如何做到這一點(迭代所有實體並重新計算字段)。我也不確定NSSortDescriptors是否可以處理Transient屬性。

+0

不幸的是,獲取的結果控制器無法對瞬態屬性或計算屬性進行排序。請參閱http://stackoverflow.com/questions/13292582/nspredicate-with-function-not-working或http://stackoverflow.com/questions/12027769/nssortdescriptor-sort-by-location瞭解類似的問題和參考文檔。 –

+0

謝謝!我看到了這一點,這就是爲什麼我認爲答案可能在計算我的核心數據實體中的值。讓我們從表格中獲取瞬態 - 如果它不是一個瞬態場,我將如何定期更新一組實體? –

+0

你真的需要一個提取的結果控制器嗎?如果您將對象提取到數組中,則可以在內存中對該數組進行排序,並將其用作表視圖的數據源。 –

回答

12

(從評論:)

取指用於基於一個(SQLite的)核心數據存儲不能排序使用請求描述符基於瞬態屬性或Objective-C的基於謂詞。

如果您不希望失去獲取結果控制器的優點(如動態表視圖更新,自動分組到段等),則必須預先計算到當前位置的距離並將其存儲在(持久)屬性。

或者,您可以獲取所有對象並將其排序在內存中。在這種情況下,您可以使用任意的排序描述符。但是這不能與提取的結果控制器結合使用,因此必須在受管對象上下文中註冊更改並在必要時重新加載表。

0

我發現了BSFetchedResultsController github project這是一個NSFetchResultsController子類,它做什麼馬丁建議,因爲它使用任意類型的描述,此外,其還註冊更改上下文排序在內存中,並計算任何指數的變化再考慮到任意排序描述符。總而言之,這是非常令人印象深刻的壯舉我用它成功地通過距離排序如下:

BSFetchedResultsController* fetchedResultsController = [[BSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil]; 

// create a location to compare distance to, e.g. current location 
CLLocation* sourceLocation = [[CLLocation alloc] initWithLatitude:55.87595153937809 longitude:-4.2578177698913855]; 

// compare the distance from both to the source location 
fetchedResultsController.postFetchComparator= ^(id a, id b) { 
    Venue* v1 = (Venue*)a; 
    Venue* v2 = (Venue*)b; 

    double d1 = [v1.coreLocation distanceFromLocation:sourceLocation]; 
    double d2 = [v2.coreLocation distanceFromLocation:sourceLocation]; 

    return [@(d1) compare:@(d2)]; 
}; 

NSError *error = nil; 
if (![fetchedResultsController performFetch:&error]) { 
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
} 

自舊項目,它沒有ARC,所以當你包含兩個文件切記要與編譯器標誌的.M -fno-objc -arc在目標階段,建立階段。另外請注意開發人員認爲代碼沒有準備好,因此如果使用它,請務必進行適當的測試。

在我上面的代碼中,我在我的Venue託管對象子類上有一個transient屬性coreLocation,您可以看到如何實現該here。此外,距離計算效率低下,您可能需要緩存對象中的距離,而不是每次比較都重新計算一次。

最後,這個項目似乎是因爲創建者Daniel Thorpe的Stackoverflow問題沒有得到答案,導致他解決了問題併發布了自己的唯一答案,所以我認爲如果您發現他的項目有用,您可以親切地致電up-vote his post像我一樣。

相關問題