【问题标题】:Core Data relationship, NSSet & ManagedObjectContext核心数据关系,NSSet & ManagedObjectContext
【发布时间】:2016-11-29 22:01:09
【问题描述】:

我想做什么

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

  1. NSManagedObjectContext 的实现是否比我目前的更简单?

  2. 不知道怎么用NSSet补全代码

该应用程序只是一个表格,其中包含员工姓名、出生日期和每个人的 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代码(导入&生成的cmets除外):

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

照片和想法

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

【问题讨论】:

  • 一次只问一个问题...

标签: swift core-data nsmanagedobject nsmanagedobjectcontext nsset


【解决方案1】:

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

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

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

【讨论】:

  • NSManagedObject 子类的实例是对象。 NSEntityDescription 类的实例是实体。不要混淆,它会使读者感到困惑。我明白你的意思,但听起来不太对劲。 “考虑重命名实体”怎么样?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多