我想创建一个函数来处理任何具有覆盖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 []
}
}
我的问题是:如何通过传递smth
和smth1
这两个额外的参数来调用类中的覆盖init函数?
let _sample = DataBaseController.Instance.addRecord(...)
提前致谢!
编辑:
它会是这样的吗? :
let _sample = DataBaseController.Instance.addRecord(Sample.self.init(smth: smth, smth1: smth1, insertIntoManagedObjectContext: _context))
答案 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
。