在带有 iCloud 的 CoreData 驱动应用程序中使用 NSSortDescriptor 和 NSFetchedResultsController 的自定义部分
Posted
技术标签:
【中文标题】在带有 iCloud 的 CoreData 驱动应用程序中使用 NSSortDescriptor 和 NSFetchedResultsController 的自定义部分【英文标题】:Custom sections with NSSortDescriptor & NSFetchedResultsController in CoreData driven app w iCloud 【发布时间】:2015-03-27 13:19:57 【问题描述】:我在使用带有 iCloud 同步的 Core Data 在应用程序中实现自定义部分时遇到问题。
我制作了一个示例应用程序来说明我的问题:它在 CoreData 中有一个事件列表(使用 FRC 获取)
事件实体:
@objc(Event)
class Event: NSManagedObject
@NSManaged var timeStamp: NSDate?
@NSManaged var name: String?
@NSManaged var sectionIdentifier :Int32
我已经根据项目的时间戳实现了自定义部分:
过去 今天 明天 接下来的 7 天 未来没有日期
enum SectionType:Int32
case inPast = 9
case Today = 10
case Tomorrow
case Next7Days
case InFuture
case NotSet = 14
func title()->String
switch self
case .inPast:
return "In Past"
case .Today:
return "Today"
case .Tomorrow:
return "Tomorrow"
case .Next7Days:
return "Next 7 Days"
case .InFuture:
return "In Future"
default:
return "No due date"
FRC 代码
private var _fetchedResultsController: NSFetchedResultsController? = nil
var fetchedResultsController: NSFetchedResultsController
if _fetchedResultsController != nil
return _fetchedResultsController!
let fetchRequest = NSFetchRequest()
let entity = NSEntityDescription.entityForName("Event", inManagedObjectContext: self.managedObjectContext!)
fetchRequest.entity = entity
fetchRequest.fetchBatchSize = 20
let sortDescriptors = [
NSSortDescriptor(key: "sectionIdentifier", ascending: true),
NSSortDescriptor(key: "timeStamp", ascending: true)
]
fetchRequest.sortDescriptors = sortDescriptors
let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest,
managedObjectContext: self.managedObjectContext!,
sectionNameKeyPath: "sectionIdentifier",
cacheName:nil)
aFetchedResultsController.delegate = self
_fetchedResultsController = aFetchedResultsController
var error: NSError? = nil
if !_fetchedResultsController!.performFetch(&error)
abort()
return _fetchedResultsController!
似乎一切正常,事件按 sectionIdentifier 分组。 但是,如果它现在与其他时区的设备同步,则由于时间差异,事件将被错误地分组。
使用瞬态属性会有所帮助,但是我不能使用 NSSortDescriptor 对部分进行排序。
有什么解决办法吗?我真的不想为每个部分填充数组等等。
亲切的问候
【问题讨论】:
您应该在按时间获取核心数据对象时使用瞬态属性,因为该部分可以动态更新,因为时间在不断变化,因此很难继续重置存储的属性***.com/questions/25960555/…跨度> 感谢您的回复!我实际上已经使用瞬态解决了我的问题。我第一次没有正确使用它们。 Apples DateSectionTitles 项目提供了帮助。 【参考方案1】:所以我通过实现一个瞬态属性解决了我的问题。
剩下的唯一问题是没有日期的事件被放在列表的顶部。 但我已经通过添加另一个属性 hasDate (Bool) 并添加第二个 NSSortDescriptor 来解决它
托管对象:
import Foundation
import CoreData
enum SectionType:String
case inPast = "10"
case Today = "11"
case Tomorrow = "12"
case Next7Days = "13"
case InFuture = "14"
case NotSet = "15"
func title()->String
switch self
case .inPast:
return "In Past"
case .Today:
return "Today"
case .Tomorrow:
return "Tomorrow"
case .Next7Days:
return "Next 7 Days"
case .InFuture:
return "In Future"
default:
return "No due date"
@objc(Event)
class Event: NSManagedObject
@NSManaged var timeStamp: NSDate?
@NSManaged var noDate: Bool
@NSManaged var name: String?
var sectionIdentifier :String?
get
var str : String
if let aDate = self.timeStamp
if aDate.isToday() || aDate.isYesterday()
str = SectionType.Today.rawValue
else if aDate.isTommorow()
str = SectionType.Tomorrow.rawValue
else if aDate.isNext7Days()
str = SectionType.Next7Days.rawValue
else if aDate.inPast()
str = SectionType.inPast.rawValue
else
str = SectionType.InFuture.rawValue
else
str = SectionType.NotSet.rawValue
return str
set
self.sectionIdentifier = newValue
func setTime(date : NSDate?)
self.willChangeValueForKey("timeStamp")
self.setValue(date, forKey: "timeStamp")
self.didChangeValueForKey("timeStamp")
if let date = date
self.noDate = false
class func keyPathsForValuesAffectingSectionIdentifier() -> NSSet
return NSSet(object: "timeStamp")
FRC:
private var _fetchedResultsController: NSFetchedResultsController? = nil
var fetchedResultsController: NSFetchedResultsController
if _fetchedResultsController != nil
return _fetchedResultsController!
let fetchRequest = NSFetchRequest()
let entity = NSEntityDescription.entityForName("Event", inManagedObjectContext: self.managedObjectContext!)
fetchRequest.entity = entity
fetchRequest.fetchBatchSize = 20
let sortDescriptors = [
// NSSortDescriptor(key: "sectionIdentifier", ascending: true),
NSSortDescriptor(key: "noDate", ascending: true),
NSSortDescriptor(key: "timeStamp", ascending: true)
]
fetchRequest.sortDescriptors = sortDescriptors
let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest,
managedObjectContext: self.managedObjectContext!,
sectionNameKeyPath: "sectionIdentifier",
cacheName:nil)
aFetchedResultsController.delegate = self
_fetchedResultsController = aFetchedResultsController
var error: NSError? = nil
if !_fetchedResultsController!.performFetch(&error)
abort()
return _fetchedResultsController!
【讨论】:
最好不要有零时间戳。 NSDate.distantFuture() 应该是默认值。以上是关于在带有 iCloud 的 CoreData 驱动应用程序中使用 NSSortDescriptor 和 NSFetchedResultsController 的自定义部分的主要内容,如果未能解决你的问题,请参考以下文章
在使用 Ensembles 进行 CoreData 和 iCloud 同步之前,我是不是需要任何 iCloud 设置?