代码之家  ›  专栏  ›  技术社区  ›  King Tech

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

  •  3
  • King Tech  · 技术社区  · 7 年前

    我正在尝试将一个自定义类与swift和CoreData一起用作可转换对象。我一直在浪费时间想弄明白,但弄不明白。我经常遇到两个错误:属性不能标记为@NSManaged,因为它的类型不能在Objective-C中表示;属性不能声明为public,因为它的类型使用内部类型。
    非常感谢您的帮助。谢谢

    我有一个名为User的CoreData对象。我还有一个名为Site的对象。
    我不希望站点对象成为CoreData对象,因为我创建站点对象的大多数时候都不希望将其添加到CoreData上下文中。

    下面您将看到类型为“Site”的“primarySite”和类型为“Site”的数组“sites”。这两行给出了我上面列出的两个错误。

    数据模型 Data Model

    用户+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 回复  |  直到 7 年前
        1
  •  4
  •   King Tech    7 年前

    我找到了解决这两个错误的方法。

    1) “无法将属性标记为@NSManaged,因为其类型无法在Objective-C中表示”
    感谢@Tom的回答,我通过将站点设置为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) {...}
    
        2
  •  3
  •   Tom Harrington    7 年前

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

    发生这种情况是因为 Site 不继承自 NSObject . Swift类不必继承自 NSObject对象 ,但核心数据可转换文件可以。如果您添加 NSObject对象 ,则不会发生该错误。

    还有其他一些问题 init(coder decoder: NSCoder) 例如,不指定任何属性值,但这些值应该很容易理解。

        3
  •  0
  •   Ace Rivera    7 年前

    由于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
    }