用于将便捷构造函数添加到核心数据库

时间:2017-02-17 10:55:55

标签: swift core-data

我想创建一个函数来处理任何具有覆盖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这两个额外的参数来调用类中的覆盖init函数?

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

提前致谢!

编辑:

它会是这样的吗? :

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

1 个答案:

答案 0 :(得分: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