Swift и CoreData с пользовательским классом в качестве трансформируемого объекта
Я пытаюсь использовать пользовательский класс с swift и CoreData в качестве трансформируемого объекта. Я тратил часы, пытаясь понять это, но не могу. Я получаю две ошибки: свойство не может быть помечено @NSManaged, потому что его тип не может быть представлен в Objective-C, и свойство не может быть объявлено общедоступным, потому что его тип использует внутренний тип.
Помощь очень ценится. Благодарю.
У меня есть объект CoreData с именем пользователя. У меня также есть объект с именем Site.
Я не хочу, чтобы объект Site был объектом CoreData, потому что в большинстве случаев, когда я создаю объект Site, я не хочу, чтобы он добавлялся в контекст CoreData.
Ниже вы увидите "primarySite" типа "Site" и "sites", который является массивом типа "Site". Эти две строки дают те же две ошибки, которые я перечислил выше.
Пользователь +CoreDataClass
import Foundation
import CoreData
public class User: NSManagedObject {
}
Пользователь +CoreDataProperties
import Foundation
import CoreData
extension User {
@nonobjc public class func fetchRequest() -> NSFetchRequest<User> {
return NSFetchRequest<User>(entityName: "User");
}
@NSManaged public var firstName: String?
@NSManaged public var lastName: String?
@NSManaged public var role: String?
@NSManaged public var primarySite: Site
@NSManaged public var sites: [Site]
}
сайт
import UIKit
class Site: NSCoding {
let identifier: Int32
let name: String
let note: String
init(with values: Dictionary<String,Any>) {
identifier = Int32(values["identifier"] as! String)!
name = values["name"] as! String
note = values["note"] as! String
}
required convenience init(coder decoder: NSCoder) {
var siteValues = [String:Any]()
siteValues["identifier"] = decoder.decodeObject(forKey: "identifier") as! String
siteValues["name"] = decoder.decodeObject(forKey: "name") as! String
siteValues["note"] = decoder.decodeObject(forKey: "note") as!
self.init(with: siteValues)
}
func encode(with coder: NSCoder) {
coder.encode(String(self.identifier), forKey: "identifier")
coder.encode(self.name, forKey: "name")
coder.encode(self.note, forKey: "note")
}
}
3 ответа
Я разобрался, как решить обе ошибки.
1) "Свойство нельзя пометить @NSManaged, так как его тип не может быть представлен в Objective-C"
Благодаря ответу @Tom я разрешаю эту ошибку, сделав Site подклассом NSObject.
class Site: NSObject, NSCoding {
2) "Свойство не может быть объявлено публичным, потому что его тип использует внутренний тип"
Я исправляю эту ошибку, добавляя "public" перед классом и функциями кодировщика и декодера.
public class Site: NSObject, NSCoding {
...
public func encode(with coder: NSCoder) {...}
public required convenience init(coder decoder: NSCoder) {...}
Property cannot be marked @NSManaged because its type cannot be represented in Objective-C
Это происходит потому, что Site
не наследуется от NSObject
, Классы Swift не должны наследоваться от NSObject
, но преобразователи Core Data делают. Если вы добавите NSObject
, эта ошибка не возникает.
Есть и другие проблемы - ваши init(coder decoder: NSCoder)
например, не присваивает значения свойств, но это должно быть легко понять.
Поскольку Site - это пользовательский класс, вы не можете использовать его в качестве типа данных в NSManagedObject.
В моем случае я сделал их тип "Двоичные данные" в вашей модели данных. Таким образом, делая его тип NSData, который является типом данных в цели c.
После этого вы можете разархивировать данные.
Например:
if let sitesArray = NSKeyedUnarchiver.unarchiveObject(with: sites) as? [[String : Any]] {
//enter your processing code here to convert them to site objects
}