阅读背景:

在CoreData驱动的app w iCloud中使用NSSortDescriptor和NSFetchedResultsController的自定义部分。

来源:互联网 

I'm having problems implementing custom section in App using Core Data with iCloud sync.

我在应用程序中使用iCloud同步的Core Data实现自定义部分时遇到了问题。

I've made a sample App to illustrate my problem : it has a list of events within CoreData (fetching using FRC)

我做了一个示例应用程序来说明我的问题:它在CoreData中有一个事件列表(使用FRC进行抓取)

Event enitity :

事件enitity:

@objc(Event)
class Event: NSManagedObject {

@NSManaged var timeStamp: NSDate?
@NSManaged var name: String?
@NSManaged var sectionIdentifier :Int32

}

I have implemented custom sections based on timeStamp of item :

我已经根据项目的时间戳实现了自定义部分:

  • In Past
  • 在过去的
  • Today
  • 今天
  • Tomorrow
  • 明天
  • Next 7 Days
  • 未来7天
  • Future
  • 未来
  • No Date

    没有日期

    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"
        }
    }
    

    }

    }

Code for FRC

代码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!
}    

Everything seems to be working, Events being grouped by sectionIdentifier. But if it's now synced with device in other timezone, the events will be grouped incorrectly because of time diff.

一切似乎都在运行,事件被分组标识符分组。但如果它现在与其他时区的设备同步,事件将被错误地分组,因为时间差异。

Using transient property would help, but then I cannot use NSSortDescriptor to sort sections.

使用瞬态属性会有所帮助,但是我不能使用NSSortDescriptor来分类。

Are there any solutions ? I really don't want to populate arrays per section and so on.

有什么解决办法吗?我不希望每个部分都填充数组,等等。

Kind Regards

亲切的问候

1 个解决方案

#1


0  

So I've solved my problem by implementing a transient property.

所以我通过实现一个瞬时属性来解决我的问题。

The only problem left Events without date are placed on top of list. But I've solved it by adding another property hasDate (Bool) and adding second NSSortDescriptor

唯一的问题是没有日期的事件被放置在列表的顶部。但是我通过添加另一个属性hasDate (Bool)并添加第二个NSSortDescriptor来解决它。

ManagedObject :

ManagedObject:

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 :

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!
    }  

分享到: