核心数据关系,NSSet& ManagedObjectContext

时间:2016-07-26 09:59:21

标签: swift core-data nsmanagedobject nsmanagedobjectcontext nsset

我想做什么

我正在构建一个演示应用程序,以了解如何使用Core Data。但我有一些问题:

  1. NSManagedObjectContext的实施方式是否比现有的更容易?

  2. 我不知道如何使用NSSet完成代码

  3. 该应用只是一个表,其中列出了员工的姓名,出生日期和每个的2个任务。任务具有多种状态(活动,完整等)。有一个项目按钮,指向另一个视图,您可以在其中输入名称和任务,并将出生日期设置为当前日期。

    我有2个实体(可以只使用EmployeeEntity吗?):

    • EmployeeEntity包含namedateOfBirth +与目标tasks的一对多TaskEntity关系
    • TaskEntity包含属性name和反向关系employee

    1。托管对象上下文实现(有更短/更容易/更好的吗?)

    AppDelegate(...didFinishLaunchingWithOptions...)中,我为第一个屏幕设置了managedObjectContext

    // Fetch Main Storyboard
        let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
    
        // Instantiate Root Navigation Controller
        let rootNavigationController = mainStoryboard.instantiateViewControllerWithIdentifier("StoryboardIDRootNavigationController") as! UINavigationController
    
        // Configure View Controller
        let viewController = rootNavigationController.topViewController as? TableTVC
    
        if let viewController = viewController {
            viewController.managedObjectContext = self.managedObjectContext
        }
    
        // Configure Window
        window?.rootViewController = rootNavigationController
    
        return true
    

    然后在prepareForSegue我传递(目的地VC中有managedObjectContext变量):

    if segue.identifier == "idTableToNew" {
            if let navVC = segue.destinationViewController as? UINavigationController {
                if let newVC = navVC.topViewController as? NewVC {
                    newVC.managedObjectContext = managedObjectContext
                }
            }
        }
    

    然后表VC中的fetchedResultsController

    lazy var frc: NSFetchedResultsController = {
        // Initialize Fetch Request
        let fetchRequest = NSFetchRequest(entityName: "EmployeeEntity")
    
        // Configure Predicate
        // Need to make changes because I only want today's date
        let predicate = NSPredicate(format: "%K == %@", "dateOfBirth", NSDate())
        fetchRequest.predicate = predicate
    
        // Initialize Fetched Results Controller
        let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
    
        // Configure Fetched Results Controller
        fetchedResultsController.delegate = self
    
        return fetchedResultsController
    }()
    

    2。我遇到的代码

    问题在于数据类型。首先,我不知道如何获得tasks'状态。其次,我不确定这是否是最佳方式。

    以下是TasksEntity.swift代码(导入和生成的评论除外):

    enum TaskStatus: Int32 {
        case Complete, Incomplete, Active, Inactive
    }
    
    class TaskEntity: NSManagedObject {
    
        @NSManaged private var statusValue: Int32
    
        var status: TaskStatus {
            get {
                return TaskStatus(rawValue: self.statusValue)!
            }
            set {
                self.statusValue = newValue.rawValue
            }
        }
    }
    

    保存数据(当我按下项目按钮时的操作):

        let name = nameField.text
        let task1Text = task1Field.text
        let task2Text = task2Field.text
    
        // Create Entities
        let employee = NSEntityDescription.entityForName("EmployeeEntity", inManagedObjectContext: managedObjectContext)
        let task = NSEntityDescription.entityForName("TaskEntity", inManagedObjectContext: managedObjectContext)
    
        // Initialize Records
        let employeeRecord = EmployeeEntity(entity: employee!, insertIntoManagedObjectContext: managedObjectContext)
        let taskRecord = TaskEntity(entity: task!, insertIntoManagedObjectContext: managedObjectContext)
        let taskRecord2 = TaskEntity(entity: task!, insertIntoManagedObjectContext: managedObjectContext)
    
        // Populate Records
        employeeRecord.name = name
        employeeRecord.dateOfBirth = NSDate()
        taskRecord.taskName = task1Text
        taskRecord.status = TaskStatus.Inactive // Apparently no errors so it might work
        taskRecord2.taskName = task2Text
        taskRecord2.status = TaskStatus.Incomplete
        let taskArray = employeeRecord.mutableArrayValueForKey("tasks")
        taskArray.addObject(taskRecord)
        taskArray.addObject(taskRecord2)
    
        // Save MOC
        do {
            try managedObjectContext.save()
        } catch {
            let saveError = error as NSError
            print("\(saveError), \(saveError.userInfo)")
        }
    

    现在VC表中的cellForRowAtIndexPath(我被困在这里):

    let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! EmployeeTVCell
    
        // Fetch Record
        let employeeRecord = frc.objectAtIndexPath(indexPath) as! EmployeeEntity
    
        // Update Cell
        if let name = employeeRecord.name {
            cell.nameLabel.text = name
        }
    
        cell.dateLabel.text = String(employeeRecord.dateOfBirth)
    
        if let tasksArray = employeeRecord.tasks?.mutableArrayValueForKey("tasks") {
            if tasksArray.count != 0 {
                cell.task1Label.text = tasksArray[0] as? String
                cell.task1Label.text = tasksArray[1] as? String
                print(tasksArray[0].status)
    
                // I think that tasksArray[index] won't work but it's what I want to achieve
            }
        }
    
        return cell
    

    照片&思想

    Employee Task

    我的猜测是我需要明确告诉它在TaskEntity NSSet中只包含tasks类型变量或类似的东西。我看到其他人使用Set s。我尝试Set<TaskEntity>并且没有错误,但我不知道如何调整代码,我将这些代码转换为数组。

1 个答案:

答案 0 :(得分:3)

Set对象的成员作为数组的常用方法是方法allObjects,但除此之外,您无法将TaskEntity对象强制转换为String

...
if let tasksArray = employeeRecord.tasks?.allObjects as? [TaskEntity] where !tasksArray.isEmpty {
    cell.task1Label.text = tasksArray[0].taskName
    cell.task1Label.text = tasksArray[1].taskName // or is it cell.task2Label ??
    print(tasksArray[0].status)
}

return cell

考虑重命名Core Data实体及其属性。实际上,NSManagedObject子类始终是一个实体,因此在名称中包含Entity是多余的。或者taskName中的属性TaskEntity可能只是name。在阅读代码时,您可以推断出name属于Task

关于status属性,您需要在Int32实体中创建statusValue属性Task,以便将值存储在Core Data中。将枚举映射到Int32的代码,反之亦然。