tableView中的sectionName与日期

时间:2015-05-30 06:26:44

标签: swift tableview

//date 
func sectionName() -> String{
    var shortDate: String
        let dateFormatter = NSDateFormatter()
        dateFormatter.dateFormat = "MMM yyyy"


 return dateFormatter.stringFromDate(NSDate())
}

//tableView 
let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchedRequest, managedObjectContext: coreDataStack.managedObjectContext!, sectionNameKeyPath: "sectionName", cacheName: nil)

//错误

is not key value coding-compliant for the key "sectionName".'

我被困在应用程序崩溃的“sectionName”我不知道为什么。

1 个答案:

答案 0 :(得分:2)

您可能已将sectionName()定义为自由函数, 而不是作为托管对象子类的属性或方法 牵强。还将“当前日期”格式化为字符串 没有多大意义,因为您可能想要对对象进行分组 根据您实体的某些日期属性。

Apple的示例项目Custom Section Titles with NSFetchedResultsController演示了如何将表视图分组 基于“timeStamp”属性的月份和年份的部分。

该项目是用 Objective-C 编写的。 这是一个简短的配方,如何在 Swift 中实现同样的目标。 在下面,我假设实体和托管对象 子类称为Event,并且应该对事件进行分组 根据{{​​1}}财产的月份和年份。

首先,添加“String”类型的 transient 属性“sectionIdentifier” 到“事件”实体。

接下来,定义timeStamp类的sectionIdentifier属性。 这可以直接在Event定义中完成 或作为扩展名:

class Event { ... }

在表视图控制器中,您必须覆盖 extension Event { var sectionIdentifier : String? { // Create and cache the section identifier on demand. self.willAccessValueForKey("sectionIdentifier") var tmp = self.primitiveValueForKey("sectionIdentifier") as? String self.didAccessValueForKey("sectionIdentifier") if tmp == nil { if let timeStamp = self.valueForKey("timeStamp") as? NSDate { /* Sections are organized by month and year. Create the section identifier as a string representing the number (year * 1000) + month; this way they will be correctly ordered chronologically regardless of the actual name of the month. */ let calendar = NSCalendar.currentCalendar() let components = calendar.components(.CalendarUnitYear | .CalendarUnitMonth, fromDate: timeStamp) tmp = String(format: "%ld", components.year * 1000 + components.month) self.setPrimitiveValue(tmp, forKey: "sectionIdentifier") } } return tmp } } 方法从中计算正确的标题 部分标识符:

titleForHeaderInSection

最后,使用“timeStamp”创建获取的结果控制器 作为第一个排序描述符,“sectionIdentifier”作为override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { /* * Creating a date formatter is "expensive". Use a static property so that * this is done only once. */ struct Formatter { static let formatter : NSDateFormatter = { let fmt = NSDateFormatter() let dateFormat = NSDateFormatter.dateFormatFromTemplate("MMMM yyyy", options: 0, locale: NSLocale.currentLocale()) fmt.dateFormat = dateFormat return fmt }() } /* Section information derives from an event's sectionIdentifier, which is a string representing the number (year * 1000) + month. To display the section title, convert the year and month components to a string representation. */ if let theSection = fetchedResultsController.sections?[section] as? NSFetchedResultsSectionInfo, let numericSection = theSection.name?.toInt() { let components = NSDateComponents() components.year = numericSection / 1000 components.month = numericSection % 1000 if let date = NSCalendar.currentCalendar().dateFromComponents(components) { let titleString = Formatter.formatter.stringFromDate(date) return titleString } } return nil }

sectionNameKeyPath

如果对象的时间戳可以修改,那么事情就会变成 稍微复杂一点。相应的“sectionIdentifier” 必须无效,以便按要求再次计算。 在Objective-C中,通过覆盖getter方法相当简单 仅限“timeStamp”属性(请参阅DateSectionTitles/APLEvent.m)。在Swift看来这似乎 要求你将“timeStamp”定义为普通的计算属性(没有@NSManaged),如https://devforums.apple.com/thread/262118?tstart=0中所述:

let fetchRequest = NSFetchRequest(entityName: "Event")
let timeStampSort = NSSortDescriptor(key: "timeStamp", ascending: false)
fetchRequest.sortDescriptors = [timeStampSort]
let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, 
        managedObjectContext: context,
        sectionNameKeyPath: "sectionIdentifier",
        cacheName: nil)

更新:从 Swift 4 开始,您必须通过添加为Objective-C运行时显式显示自定义Core Data属性 class Event: NSManagedObject { //@NSManaged var timeStamp : NSDate var timeStamp: NSDate? { get { self.willAccessValueForKey("timeStamp") let tmp = self.primitiveValueForKey("timeStamp") as? NSDate self.didAccessValueForKey("timeStamp") return tmp } set { self.willChangeValueForKey("timeStamp") self.setPrimitiveValue(newValue, forKey: "timeStamp") self.didChangeValueForKey("timeStamp") // If the time stamp changes, the section identifier become invalid. self.setPrimitiveValue(nil, forKey: "sectionIdentifier") } } override class func keyPathsForValuesAffectingValueForKey(key: String) -> Set<NSObject> { var keyPaths = super.keyPathsForValuesAffectingValueForKey(key) if key == "sectionIdentifier" { keyPaths.insert("timeStamp") } return keyPaths } } 属性,例如

@objc

有关此更改的详细信息,请参阅