使用 CoreData 以编程方式创建 entity/table,并将值插入到 Swift 3 中的实体中,用于 iOS

Programmatically create entity/table using CoreData and insert values into that entity in Swift 3 for iOS

我一直在尝试寻找一种方法,在 Swift 3 的 运行 时间以编程方式为 iOS 平台创建数据库 entity/table。 请详细说明过程。我已经关注了其他链接,但没有任何效果,我无法正确理解该过程,因此请使用工作代码解释整个过程,而不是提供其他现有链接。

从 XCode 添加了一个 table,我可以在 [=57] 上执行与数据库相关的操作(插入行、删除、更新) =] 但我无法找到在 table 上执行以下操作的方法,它将在 运行 时间以编程方式创建。 需要进行以下操作

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

Insert Values - 然后用户将拥有将值插入实体的界面。实体的名称将是已知的,实体中一行的值将由用户输入。点击按钮时,该行应插入 entity/database-table.

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

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

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

我试过下面的代码-:

    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 element - 0 : (entity: TestEntity; id: 0x600000422f80 ; data: { columnOne = "WHY SO SERIOUS?"; })

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

您描述的某些步骤对于 Core Data 来说根本不可能。或者至少,并非没有让事情 极其 复杂和困难。要求完整的工作代码是不合理的,因为您对核心数据有一组极其不寻常和复杂的要求。

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

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

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

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

只需使用以下代码即可退出:

import Foundation
import CoreData

class CoreData {

static let shared = CoreData()

let dataBase = NSManagedObjectModel()
   
let dbTable:NSEntityDescription = {
    let tableEntity = NSEntityDescription()
    tableEntity.name = "NEntity"
    tableEntity.managedObjectClassName = "NEntity"
    return tableEntity
}()

// The attributes each item in the table will have. e.g. id, name, password, date
let dbTableAttribute:NSAttributeDescription =  {
    let tblAttr = NSAttributeDescription()
    tblAttr.name = "id"
    tblAttr.attributeType = .integer64AttributeType
    tblAttr.isOptional = true
    return tblAttr
}()

lazy var persistentContainer: NSPersistentContainer = {
    let container = NSPersistentContainer(name: "APICall", managedObjectModel: dataBase)
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
    return container
}()

private init(){
    dataBase.entities.append(dbTable)
    dbTable.properties.append(dbTableAttribute)
}

func saveContext () {
    let context = persistentContainer.viewContext
    if context.hasChanges {
        do {
            try context.save()
        } catch {
            let nserror = error as NSError
            fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
        }
    }
}
}




// MARK: - Defining the class for the table, you can put this in a seperate file if you want but for ease of copying I put them together

@objc(NEntity)
public class NEntity: NSManagedObject {

// Variables must be NSManaged to be saved to the database
@NSManaged var id:Int64

// Call this function to save a new item to the table
static func addEntity(_ id:Int) {
    
    let entityName = NSStringFromClass(self)
    
    let moc = CoreData.shared.persistentContainer.viewContext
    guard let entity =  NSEntityDescription.insertNewObject(forEntityName:entityName, into: moc)
            as? NEntity
    else { print("Could not find entity: \(entityName) in database: \(CoreData.shared.persistentContainer.name)"); return }
    
    entity.id = Int64(id)

    // Update database
    CoreData.shared.saveContext()
}

//Call this function to search the database for items matching the id, see removeEntityWithAttribute() for example
func fetchEntityByAttribute(id:Int, completion:@escaping ([NEntity]?) -> ()){
    let moc = CoreData.shared.persistentContainer.viewContext

    let fetchRequest = NEntity.fetchRequest()
    
    fetchRequest.predicate = NSPredicate(format: "id == %d", id)
    moc.perform {

        guard let  result = try? fetchRequest.execute() else {
            return
        }
        if result.count > 0 {
            completion((result as! [NEntity]))
        }else {
            completion(nil)
        }
    }
    
}

//Call this function to delete entities from the database with the matching id
func removeEntityWithAttribute(id:Int) {
    
    let moc = CoreData.shared.persistentContainer.viewContext

    fetchEntityByAttribute(id:id) { matchedEntities in
        
        if let matchingEntities = matchedEntities {
            matchingEntities.forEach(){
                moc.delete([=10=])
                CoreData.shared.saveContext()
            }
        }
        
    }
}
}

只需在代码中的任意位置调用 NEntity.addEntity(5) 即可在数据库中保存一个 ID 为 5 的项目。请确保为它们提供唯一的 ID,以便您可以编辑和删除它们。

来源:

https://tigi44.github.io/ios/iOS,-Swift-Core-Data-Model-in-a-Swift-Package/

https://dmytro-anokhin.medium.com/core-data-and-swift-package-manager-6ed9ff70921a