在Swift

时间:2016-12-28 07:34:28

标签: arrays swift core-data

我正在使用CoreData和Swift 3,但我认为这更像是关于NSPredicates,NSSortDescriptors和NSFetchedResultsController的一般性问题......

我有一个具有整数属性的实体,我想要排序,但我需要根据传入的整数拆分结果,并按降序独立排序两半,然后将它们组合起来。具有属性< =分裂值的所有实体都在前面(下降),并且所有实体都是>分裂值在末尾(降序)。

以下是一个例子:

正常获取的结果按整数属性按降序排序:

[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中插入排序功能。

2 个答案:

答案 0 :(得分:1)

假设您有一个数据存储,其中已插入了10个名为Number的实体。模型实体有一个名为value的属性Int32,您要对其进行排序(数据存储中的值范围为1到10)。

使用此功能可根据键值拆分数据,并使用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

希望这有帮助!

答案 1 :(得分:0)

您可以围绕两个NSFetchedResultsController创建包装器(下一个 resultsController )。
第一个resultsController应该在(&lt; =)阈值之前获取值,第二个resultsController应该在(&gt;)阈值之后获取值。
之后,包装器可以将所需数据作为来自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>;
}