2016-12-28 44 views
1

我使用CoreData和斯威夫特3,但我認爲這更多的是NSPredicates,NSSortDescriptors和NSFetchedResultsController一般問題...組合兩個NSPredicates獨立NSSortDescriptors斯威夫特

我有一個實體與整數屬性,我想排序,但我需要根據傳入的整數拆分結果,並按降序獨立地對這兩部分進行排序,然後將它們合併。所有具有<屬性的實體=分裂值在前(降序),所有>分裂值的實體在末尾(降序)。

下面是一個例子:

[10,9,8,7,6,5,4,3,2,1]

:由整數屬性按降序排序

正常讀取的結果

鑑於 「5」 的分裂值,最後的結果應該是:

[5,4,3,2,1,10,9%,8,7%,6]

或者用分裂值8,最終結果應該是:

[8,7,6,5,4個,3個,2,1,10,9]

什麼我做的是創造一個翻轉點,天方式一個月輥 - 在28日,29日,30日或31日。在我的情況下,翻車點是動態的,我沒有與天工作。

我無法弄清楚如何用謂詞和排序描述符做到這一點。這甚至有可能嗎?

我已閱讀關於使用實體中的「sortOrder」屬性進行多次讀取。基本上,取一次,將結果放入一個數組中,按照我想要的方式對數組進行排序,然後在每個實體上設置「sortOrder」屬性,保存上下文,然後再次提取,按「sortOrder」進行排序。我可以做到這一點,但我希望有更優雅的東西。

下面是一些代碼,做一個陣列上的正確排序:

func rolloverSort(withArray: [Int], andIndex index: Int) -> [Int] { 
    let inputArray = withArray.sorted() 
    var newArray = [Int]() 
    var splitIndex: Int = 0 

    for item in inputArray { 
     if item <= index { 
      newArray.insert(item, at: 0) 
      splitIndex += 1 
     } 
     if item > index { 
      newArray.insert(item, at: splitIndex) 
     } 
    } 
    return newArray 
} 

結果將駕駛一個UITableView,所以我需要一個NSFetchedResultContoller的背景下,這是內做到這一點所以我想謂詞和排序描述符。

這是我NSFetchedResultsController和周圍的一些背景:

// sortMethod (used in sortDescriptor) is set via an action sheet button. 
// Currently it's just a string for the entity attribute to sort on. 
// The closure on each button sets self._fetchedRequestController = nil, 
// sets sortMethod to the desired sorting string, then calls 
// tableView.reloadData(). 

var fetchedResultsController: NSFetchedResultsController<Entity> { 

    if _fetchedResultsController != nil { 
     return _fetchedResultsController! 
    } 

    let fetchRequest: NSFetchRequest<Entity> = Entity.fetchRequest() 
    fetchRequest.fetchBatchSize = 20 

    let sortDescriptor = NSSortDescriptor(key: sortMethod, ascending: false) 

    fetchRequest.sortDescriptors = [sortDescriptor] 

    let aFetchedResultsController = NSFetchedResultsController(
     fetchRequest: fetchRequest, 
     managedObjectContext: managedObjectContext!, 
     sectionNameKeyPath: nil, 
     cacheName: "Master") 

    aFetchedResultsController.delegate = self 
    _fetchedResultsController = aFetchedResultsController 

    do { 
     try _fetchedResultsController!.performFetch() 
    } catch { 
     // FIXME: Replace error handling stub. 
     let nserror = error as NSError 
     fatalError("Unresolved error \(nserror), \(nserror.userInfo)") 
    } 

    return _fetchedResultsController! 
} 

var _fetchedResultsController: NSFetchedResultsController<Card>? = nil 

,與簡單的分揀工作,但我在努力弄清楚如何從A.Jam排序功能插槽。

+0

它是重要的只是,沒有任何其他的程序,但使用排序謂詞進行排序? – Astoria

+0

不,我想我不必使用謂詞。目標是嘗試使用單個獲取的結果。我不在乎如何完成。獲取的結果是驅動一個UITableView,如果這很重要。 –

+0

我可以提供的第一個決定是將數組拆分爲兩個,對它們進行排序然後重新加入。但是,僅僅使用一個過程可能是一個有趣的任務。 – Astoria

回答

1

假設您有一個數據存儲,其中包含10個實體,名爲Number已插入。模型實體有一個屬性,您需要對其進行排序(數據存儲區中的值範圍爲1到10),其類型爲Int32

使用此功能根據您的鍵值來分割你的數據和使用的NSSortDescriptor實例對它們進行排序:

func fetchSortEntites(basedOn integer: Int32) -> ([Int32], [Number]){ 

     var sortedNumberArray: [Int32] = [] 
     var sortedManagedObjects: [Number] = [] 

//  Phase 1 

     let predicate1 = NSCompoundPredicate(format: "value <= %ld", integer) 
     let sortDescriptor1 = NSSortDescriptor(key: "value", ascending: false) 
     let fetchRequest1 = NSFetchRequest<Number>(entityName: "Number") 
     fetchRequest1.predicate = predicate1 
     fetchRequest1.sortDescriptors = [sortDescriptor1] 

     do{ 
      let managedObjects = try managedObjectContext.fetch(fetchRequest1) 
      for managedObject in managedObjects{ 
       sortedNumberArray.append(managedObject.value) 
       sortedManagedObjects.append(managedObject) 
      } 
     } catch let error as NSError { 
      print(error.debugDescription) 
      fatalError("*** Failed to fetch managed objects from the context!") 
     } 


//  Phase 2 

     let predicate2 = NSCompoundPredicate(format: "value > %ld", integer) 
     let sortDescriptor2 = NSSortDescriptor(key: "value", ascending: false) 
     let fetchRequest2 = NSFetchRequest<Number>(entityName: "Number") 
     fetchRequest2.predicate = predicate2 
     fetchRequest2.sortDescriptors = [sortDescriptor2] 

     do{ 
      let managedObjects = try managedObjectContext.fetch(fetchRequest2) 
      for managedObject in managedObjects{ 
       sortedNumberArray.append(managedObject.value) 
       sortedManagedObjects.append(managedObject) 
      } 
     } catch let error as NSError { 
      print(error.debugDescription) 
      fatalError("*** Failed to fetch managed objects from the context!") 
     } 


     return (sortedNumberArray, sortedManagedObjects) 
    } 


} 

結果:

let myTuple = fetchSortEntites(basedOn: 5) 

    for number in myTuple.0{ 
     print (number) 
    } 

enter image description here

let myTuple = fetchSortEntites(basedOn: 8) 

    for number in myTuple.0{ 
     print (number) 
    } 

enter image description here

希望這有助於!

+0

有關如何使用NSFetchedResultsController插入它的任何提示? –

+0

我用我的NSFetchedResultsController和一些上下文更新了我的問題。 –

+0

你好@EricSopher,我不認爲你可以使用NSFetchRequest的一個實例獲取結果(以你想要的順序)。此外,您不能將多個提取請求組合到一個NSFetchedResultsController實例中。如果您找到解決此問題的方法,請告訴我。你可以閱讀[this](http://stackoverflow.com/questions/17994961/ios-two-entities-fetch-merge-and-sort)發佈一些進一步的信息。祝你好運。 –

0

您可以在兩個NSFetchedResultsController(接下來的resultsController)周圍創建包裝。
第一個resultsController應該在(< =)閾值之前獲取值,第二個resultsController應該在(>)閾值之後獲取值。
之後,包裝器可以從requestControllers返回所需的數據作爲數據聯合。
例如:

//Get count cells 
int countCells = resultsController1.sections.first.numberOfObjects + resultsController2.sections.first.numberOfObjects; 
<...> 
//Get value for cell 
int value = 0; 
if (cellIndex >= <counts_in_first_resultsController>) 
{ 
    value = <Get_from_the_second>; 
} 
else 
{ 
    value = <Get_from_the_first>; 
}