Swift如何对合并后的CoreData NSManagedObject数组进行升序排序
嗨,这个问题其实很常见,合并两个CoreData查询结果后排序的话,有两种很实用的方式,结合你之前用过NSSortDescriptor的经验,我给你详细说说:
先完成数组合并
不管用哪种排序方式,第一步都是把两次Fetch Request的结果合并成一个数组:
// Swift 示例 let firstFetchResults: [YourManagedObjectType] = ... // 第一次请求结果 let secondFetchResults: [YourManagedObjectType] = ... // 第二次请求结果 let combinedArray = firstFetchResults + secondFetchResults
// Objective-C 示例 NSArray<YourManagedObjectType *> *firstFetchResults = ...; NSArray<YourManagedObjectType *> *secondFetchResults = ...; NSArray<YourManagedObjectType *> *combinedArray = [firstFetchResults arrayByAddingObjectsFromArray:secondFetchResults];
记得把YourManagedObjectType替换成你自己的NSManagedObject子类(比如Task、Contact这类)。
方法一:用原生闭包/Block自定义排序(灵活度高)
如果需要自定义排序逻辑(比如处理属性为nil的特殊场景),用这种方式最方便。比如你要按date属性升序排序,且让nil的日期排在最前面:
Swift 代码示例
let sortedArray = combinedArray.sorted { obj1, obj2 in let date1 = obj1.value(forKey: "date") as? Date let date2 = obj2.value(forKey: "date") as? Date switch (date1, date2) { case (nil, nil): return false // 两个都为nil,顺序不变 case (nil, _): return true // nil的排在前面 case (_, nil): return false // 非nil的排在前面 case (let d1?, let d2?): return d1 < d2 // 正常升序比较 } }
如果是字符串属性(比如name),建议用本地化排序避免语言问题:
let sortedArray = combinedArray.sorted { obj1, obj2 in guard let name1 = obj1.value(forKey: "name") as? String, let name2 = obj2.value(forKey: "name") as? String else { return false } return name1.localizedStandardCompare(name2) == .orderedAscending }
Objective-C 代码示例
NSArray<YourManagedObjectType *> *sortedArray = [combinedArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { NSDate *date1 = [obj1 valueForKey:@"date"]; NSDate *date2 = [obj2 valueForKey:@"date"]; if (!date1 && !date2) return NSOrderedSame; if (!date1) return NSOrderedAscending; // nil排前面 if (!date2) return NSOrderedDescending; return [date1 compare:date2]; }];
方法二:复用NSSortDescriptor快速排序(代码简洁)
既然你之前单独查询时已经用过NSSortDescriptor,可以直接复用这个逻辑,不需要重新写比较逻辑:
Swift 代码示例
// 创建和之前一样的排序描述符 let sortDescriptor = NSSortDescriptor(key: "date", ascending: true) // 利用NSArray的排序方法,再桥接回Swift数组 let sortedArray = (combinedArray as NSArray).sortedArray(using: [sortDescriptor]) as! [YourManagedObjectType]
Objective-C 代码示例
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"date" ascending:YES]; NSArray<YourManagedObjectType *> *sortedArray = [combinedArray sortedArrayUsingDescriptors:@[sortDescriptor]];
这种方式的好处是代码更简洁,而且和你之前的查询排序逻辑保持一致,不容易出错。
最后提醒下:如果你的NSManagedObject子类已经生成了属性的getter方法,也可以直接用属性名代替value(forKey:),比如obj1.date,这样代码可读性更高,还能避免字符串写错的问题。
内容的提问来源于stack exchange,提问作者User382
相关产品推荐
相关产品推荐

