使用自定义类作为可转换对象的Swift和CoreData

5
我正在尝试使用自定义类与Swift和CoreData作为可转换对象。 我已经浪费了几个小时试图弄清楚它,但是无法做到。 我不断收到两个错误:无法将属性标记为@NSManaged,因为其类型无法在Objective-C中表示,以及无法声明公共属性,因为其类型使用内部类型。
非常感谢您的帮助。谢谢。
我有一个名为User的CoreData对象。 我还有一个名为Site的对象。
我不希望Site对象成为CoreData对象,因为大多数情况下我创建Site对象时不想将其添加到CoreData上下文中。
下面您将看到类型为“Site”的“primarySite”和类型为“Site”的数组“sites”。这两行给出了我上面列出的两个错误。
数据模型 Data Model User+CoreDataClass
import Foundation
import CoreData

public class User: NSManagedObject {
}

User+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")
    }
}

1
除非您的网站实际上比您的代码片段所暗示的更复杂,否则我建议将其作为一个新实体添加,并将primarySite和sites定义为从用户到网站的关系,而不是可转换的属性。 - pbasdf
你展示了User正在使用手动/无代码生成,并且你在User上有一个扩展。User类定义在哪里? - Tom Harrington
用户有两个由Xcode生成的文件。User+CoreDataClass.swift除了类声明之外没有任何内容,所以我认为不需要包含它。 - King Tech
3个回答

4
我找到了解决这两个错误的方法。
1)“属性不能被标记为@NSManaged,因为它的类型在Objective-C中无法表示” 感谢@Tom的回答,我通过将Site设置为NSObject的子类来解决此错误。
class Site: NSObject, NSCoding {


2) "属性不能声明为public,因为其类型使用了内部类型"
     我解决了这个错误,通过在类、编码器和解码器函数前添加"public"。

public class Site: NSObject, NSCoding {
...
public func encode(with coder: NSCoder) {...}
public required convenience init(coder decoder: NSCoder) {...}

3
这是因为Site没有继承自NSObject。Swift类不必继承自NSObject, 但Core Data可转换对象必须继承它。如果您添加NSObject,则不会出现该错误。还有一些其他问题--例如,您的init(coder decoder: NSCoder)没有分配任何属性值--但这些应该很容易解决。

我忘记复制init(coder decoder: NSCoder)中调用self.init()的那一行了。我已经编辑了问题。谢谢。 - King Tech

0

由于Site是一个自定义类,所以你不能在NSManagedObject中使用它作为数据类型。

在我的情况下,我将它们的类型设置为“二进制数据”在你的数据模型中。 因此,将其类型设置为NSData,这是objective c中的一种数据类型。

之后,您可以对数据进行解档。

例如:

if let sitesArray = NSKeyedUnarchiver.unarchiveObject(with: sites) as? [[String : Any]] {
    //enter your processing code here to convert them to site objects
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接