简体   繁体   English

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

[英]Swift And CoreData With Custom Class As Transformable Object

I am trying to use a custom class with swift and CoreData as a transformable object. 我试图使用swift和CoreData作为可转换对象的自定义类。 I have been wasting hours trying to figure it out but cannot. 我一直在浪费时间试图弄清楚但不能。 I keep getting two errors: Property cannot be marked @NSManaged because its type cannot be represented in Objective-C and Property cannot be declared public because its type uses an internal type. 我不断收到两个错误:属性无法标记为@NSManaged,因为其类型无法在Objective-C中表示,并且Property无法声明为public,因为其类型使用内部类型。
Help is greatly appreciated. 非常感谢帮助。 Thanks. 谢谢。

I have a CoreData object named User. 我有一个名为User的CoreData对象。 I also have an object named Site. 我还有一个名为Site的对象。
I don't want the Site object to be a CoreData object because the majority of the times that I create a Site object I don't want it added to the CoreData context. 我不希望Site对象成为CoreData对象,因为我创建Site对象的大多数时候我不希望它添加到CoreData上下文。

Below you will see "primarySite" of type "Site" and "sites" which is an array of type "Site". 您将在下面看到“site”类型的“primarySite”和“Site”类型的“sites”。 These two lines give the same two errors I listed above. 这两行给出了我上面列出的两个错误。

Data Model 数据模型 数据模型

User+CoreDataClass 用户+ CoreDataClass

import Foundation
import CoreData

public class User: NSManagedObject {
}

User+CoreDataProperties 用户+ 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]
}

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

Property cannot be marked @NSManaged because its type cannot be represented in Objective-C

This happens because Site does not inherit from NSObject . 发生这种情况是因为Site不从NSObject继承。 Swift classes don't have to inherit from NSObject , but Core Data transformables do. Swift类不必从NSObject继承,但Core Data转换可以继承。 If you add NSObject , that error doesn't occur. 如果添加NSObject ,则不会发生该错误。

There are some other problems-- your init(coder decoder: NSCoder) doesn't assign any property values, for example-- but those should be easy to figure out. 还有一些其他问题 - 你的init(coder decoder: NSCoder)没有分配任何属性值,例如 - 但这些应该很容易理解。

I figured out how to resolve both errors. 我想出了如何解决这两个错误。

1) "Property cannot be marked @NSManaged because its type cannot be represented in Objective-C" 1) “属性不能标记为@NSManaged,因为它的类型不能用Objective-C表示”
Thanks to @Tom's answer I resolve this error by making Site a subclass of NSObject. 感谢@ Tom的回答我通过使Site成为NSObject的子类来解决这个错误。

class Site: NSObject, NSCoding {


2) "Property cannot be declared public because its type uses an internal type" 2) “属性不能公开,因为它的类型使用内部类型”
I resolve this error by making adding "public" before the class, and the encoder and decoder functions. 我通过在类之前添加“public”以及编码器和解码器功能来解决此错误。

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

Since Site is a custom class, you cannot use it as a datatype in your NSManagedObject. 由于Site是自定义类,因此不能将其用作NSManagedObject中的数据类型。

In my case, I made their type "Binary Data" in your Data Model . 就我而言,我在您的数据模型中创建了“二进制数据”类型。 Thus, making its type NSData which is a data type in objective c. 因此,使其类型NSData成为目标c中的数据类型。

After this, you can unarchived the data. 在此之后,您可以取消归档数据。

For example: 例如:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM