使用 CoreData 以编程方式创建实体/表,并在 Swift 3 for iOS 中将值插入该实体

Posted

技术标签:

【中文标题】使用 CoreData 以编程方式创建实体/表,并在 Swift 3 for iOS 中将值插入该实体【英文标题】:Programmatically create entity/table using CoreData and insert values into that entity in Swift 3 for iOS 【发布时间】:2017-11-16 06:00:55 【问题描述】:

我一直在尝试找到一种方法,在 ios 平台的 Swift 3 中以编程方式在运行时创建数据库实体/表。 请详细说明过程。我关注了其他链接,但对我没有任何帮助,我无法正确理解该过程,因此请使用有效代码解释整个过程,而不是提供其他现有链接。

XCode 又添加了一个表,我可以在该表上执行与数据库相关的操作(插入行、删除、更新),但我无法找到一种方法来在该表上执行以下操作将在运行时以编程方式创建的表。 需要执行以下操作。

添加实体 - 在界面中,用户可以添加实体名称、列数、列名称,然后点击按钮,应使用 CoreData 将实体创建到数据库中。用户可以从界面添加任意数量的表格。

插入值 - 然后用户将有接口将值插入到实体中。实体的名称将是已知的,并且实体中一行的值将由用户输入。点击按钮时,该行应插入到实体/数据库表中。

获取值 - 用户可以选择从实体中获取所有保存的值。需要时随时使用。

更新值 - 用户将能够更新以编程方式创建的表中存在的任何值。

删除实体 - 还有一个删除数据库实体的选项。点击按钮时,实体的名称将被传递给函数,并且该实体/数据库表将从数据库中删除。

我已经尝试了以下代码-:

    let model = NSManagedObjectModel()
    let entityName = "TestEntity"
    let entity = NSEntityDescription()
    entity.name = entityName
    entity.managedObjectClassName = entityName

    // Creating a attribute
    let remoteURLAttribute = NSAttributeDescription()
    remoteURLAttribute.name = "columnOne"
    remoteURLAttribute.attributeType = .stringAttributeType
    remoteURLAttribute.isOptional = true
    remoteURLAttribute.isIndexed = true

    var properties = Array<NSAttributeDescription>()
    properties.append(remoteURLAttribute)
    // Adding the attribute to the entity
    entity.properties = properties

    // Adding the entity into the model
    model.entities = [entity]

    do 
        try CoreDataManager.managedObjectContext.save()
     catch 
        print(error)
    

    // Inserting the data into the entity
    let testEntity = NSManagedObject(entity: entity, insertInto: CoreDataManager.managedObjectContext)
    testEntity.setValue("WHY SO SERIOUS?", forKey: "columnOne")

    do 
        try CoreDataManager.managedObjectContext.save()
     catch 
        print(error)
    

    // Fetching the data from the entity
    let request = NSFetchRequest<NSFetchRequestResult>()
    request.entity = entity
    request.propertiesToFetch = ["columnOne"]
    request.returnsDistinctResults = false
    do 
        let results = try CoreDataManager.managedObjectContext.fetch(request)
        print(results)
     catch 

    

我在结果中得到以下值 -:

▿ 1 个元素 - 0 : (实体:TestEntity;ID:0x600000422f80 ; 数据: columnOne = "为什么这么严重?"; )

但是我没有任何方法可以从其他任何地方获取该实体的值,也无法通过在这种情况下使用 TestEntity 的实体名称将值从其他地方插入到实体中。

【问题讨论】:

【参考方案1】:

您描述的某些步骤根本无法使用 Core Data。或者至少,不会让事情变得非常复杂和困难。要求提供完整的工作代码是不合理的,因为您对 Core Data 有一套极其不寻常和复杂的要求。

确实NSManagedModel 和所有实体都是可变的,并且可以在代码中更改。除了,所有这些更改必须在您使用该模型加载任何数据之前进行。致电loadPersistentStores(_:)(如果您使用NSPersistentContainer)或addPersistentStore(ofType:configurationName:at:options:)(如果您不使用NSPersistentContainer)后,您将无法进行更改。这样做会导致您的应用崩溃的运行时错误。

因此,提供用户界面来动态创建和删除 Core Data 实体的想法并不是一个真正的选择。您可以创建和删除实体的实例,但不能创建和删除实体描述。

如果你愿意做很多艰苦的工作,你也许可以得到一些接近的东西。使用 Core Data 最接近的方法是在需要更改的任何时候创建一个全新的托管对象模型。然后使用此模型将所有数据复制到新的持久存储文件(包括处理非轻量级迁移所需的任何自定义代码)。然后删除旧模型和持久存储文件以及对您之前使用它们获取的所有对象的所有引用。

这将很难做到,并且可能会遇到我没有想到的无法预料的困难。我强烈建议不要尝试对 Core Data 执行此操作,因为它不是为以这种方式使用而设计的。

【讨论】:

那么我怎样才能在 swift 3 中满足当前的要求呢? 你不会,除非你愿意自己做很多艰苦的工作。更多详情,请重新阅读答案。

以上是关于使用 CoreData 以编程方式创建实体/表,并在 Swift 3 for iOS 中将值插入该实体的主要内容,如果未能解决你的问题,请参考以下文章

基于coreData信息在objective-c中以编程方式创建图像

以编程方式获取 Core Data 实体描述

以编程方式在运行时删除或添加属性到CoreData

以编程方式检查核心数据实体是不是被索引

为现有实体创建新的 CoreData 属性时 Swift 崩溃

在运行时查找 CoreData 模型的实体