【问题标题】:Generic function for adding convenience constructors into the core data base将便利构造函数添加到核心数据库的通用函数
【发布时间】:2017-07-06 20:56:45
【问题描述】:

我想创建一个函数来处理任何类型的具有重写 init 函数的对象。到目前为止,我只使用了重写的 init 函数,但是如果我想每次都对这些对象进行其他操作,我必须使用一些逻辑部分编写额外的代码。为了避免这种情况并使代码干净,我必须制作通用函数作为参数T.Type

这是我的示例代码,它显示了工作部分:

import Foundation
import CoreData


extension Sample {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Sample> {
        return NSFetchRequest<Sample>(entityName: "Sample");
    }

    @NSManaged public var smth: String
    @NSManaged public var smth1: Double

    convenience init(smth: String, smth1: Double, insertIntoManagedObjectContext _context: NSManagedObjectContext!) {
        let _enitity = NSEntityDescription.entity(forEntityName: "Sample", in: _context)
        self.init(entity: _entity, insertInto: _context)
        self.smth = smth
        self.smth1 = smth1
    }

}

然后我像这样初始化对象:

    let _context = DataBaseController.getContext()

let _sample: Sample = Sample(smth: smth, smth1: smth1 insertIntoManagedObjectContext: _context)
    DataBaseController.saveContext()

通过以下示例:Example

我已经实现了这些功能:

func addRecord<T: NSManagedObject>(_ type : T.Type) -> T {
        let _entityName = T.description()
        let _context = DataBaseController.persistentContainer.viewContext
        let _entity = NSEntityDescription.entity(forEntityName: _entityName, in: _context)
        let _record = T(entity: _entity!, insertInto: _context)
        return _record
    }

    func recordsInDataBase<T: NSManagedObject>(_ type : T.Type) -> Int {
        let _records = allRecords(T.self)
        return _records.count
    }

    func allRecords<T: NSManagedObject>(_ type : T.Type, sort: NSSortDescriptor? = nil) -> [T] {
        let _context = DataBaseController.persistentContainer.viewContext
        let _request = T.fetchRequest()
        do {
            let _results = try _context.fetch(_request)
            return _results as! [T]
        } catch {
            print("Error : \(error)")
            return []
        }
    }

我的问题是:如何通过传递smthsmth1 这两个额外的参数从类中调用我的重写初始化函数?

let _sample = DataBaseController.Instance.addRecord(...)

提前致谢!

编辑:

会是这样吗? :

let _sample = DataBaseController.Instance.addRecord(Sample.self.init(smth: smth, smth1: smth1, insertIntoManagedObjectContext: _context))

【问题讨论】:

  • addRecord 的意义何在? let _sample: Sample = Sample(smth: smth, smth1: smth1 insertIntoManagedObjectContext: _context) 已经向数据库添加了一个新对象。
  • 那么这样尝试没有意义吗?然后每当我要调用其他方法时,我需要作为参数发送Sample.self,它会知道我指向Sample 的实例?
  • 我不太明白你的意思。你的最终目标是什么?
  • 为了让我的代码更清晰,而不需要不必要地重新声明从数据库获取信息并保存它。
  • 我实际上有一个解决方法,我会测试它并更新我的答案。

标签: swift core-data


【解决方案1】:

你不能这样做。

在您链接的示例中,它展示了如何使用简洁的小功能保存和查询数据库。您不能神奇地将额外参数传递给函数并期望它们被接受并用于创建新的“记录”。

如果您向下滚动一下,回答者实际上会向您展示如何使用这些功能:

let name = "John Appleseed"

let newContact = addRecord(Contact.self)
newContact.contactNo = 1
newContact.contactName = name

这就是您使用addRecord 的方式。你调用addRecord,传入WhateverType.self,并将返回值赋给一个变量。之后,您直接设置变量的属性,不是使用初始化器

我想出了这个(不是很优雅)的解决方案:

extension NSManagedObject {
    func initialize(with properties: [String: Any]) {

    }
}

class Sample : NSManagedObject {
    override func initialize(with properties: [String : Any]) {
        self.smth = properties["smth"] as! String
        self.smth1 = properties["smth1"] as! Double
    }

    @NSManaged var smth: String
    @NSManaged var smth1: Double

    convenience init(properties: [String: Any], insertIntoManagedObjectContext _context: NSManagedObjectContext!) {
        let _enitity = NSEntityDescription.entity(forEntityName: "Sample", in: _context)
        self.init(entity: _enitity!, insertInto: _context)
    }
}

现在所有NSManagedObject 都有这个initialize(with:) 方法。因此,在addRecord 方法中,您可以调用它来初始化具有所需属性的新托管对象:

func addRecord<T: NSManagedObject>(_ type : T.Type, properties: [String: Any]) -> T {
    let _entityName = T.description()
    let _context = DataBaseController.persistentContainer.viewContext
    let _entity = NSEntityDescription.entity(forEntityName: _entityName, in: _context)
    let _record = T(entity: _entity!, insertInto: _context)
    _record.initialize(with: properties)
    return _record
}

示例用法:

addRecord(Sample.self, properties: ["smth": "Hello", "smth1": 1])

这样做的坏处当然是没有类型安全。您传递给addRecord 的每个属性都是Any 类型。

【讨论】:

  • 是的,我会考虑这个。感谢您的回答 !我明白你的意思了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-01
  • 2017-06-26
  • 2018-04-15
  • 1970-01-01
  • 1970-01-01
  • 2021-05-03
相关资源
最近更新 更多