Ios 如何从json解析到核心数据模型,其中有一个带有关联值的枚举?

Ios 如何从json解析到核心数据模型,其中有一个带有关联值的枚举?,ios,json,swift,core-data,enums,Ios,Json,Swift,Core Data,Enums,模型 核心数据模型 struct UserList { var privacy: Access var sharing: Access } enum Access: { case `private` case friendsOnly case someFriends(ids: [String]) case `public` } CoreData设置: 问题: 如何将Codable添加到UserList以从json获取模型 如何将可编码添

模型

核心数据模型

struct UserList {

    var privacy: Access
    var sharing: Access
}

enum Access: {

    case `private`
    case friendsOnly
    case someFriends(ids: [String])
    case `public`
} 
CoreData设置:

问题:

  • 如何将Codable添加到UserList以从json获取模型
  • 如何将可编码添加到核心数据模型?能够直接将模型从json保存到核心数据
  • 如何从核心数据UserListModel初始化UserList模型
  • 如何将Codable添加到UserList以从json获取模型
  • 使用(例如,不安全):

  • 如何将可编码添加到核心数据模型?能够直接将模型从json保存到核心数据
  • 如何使用(例如,不安全):

  • 如何从核心数据UserListModel初始化UserList模型
  • 使用(例如,不安全):

    让appDelegate=UIApplication.shared.delegate为!AppDelegate
    让上下文=appDelegate.persistentContainer.viewContext
    let请求:NSFetchRequest=UserListModel.fetchRequest()
    让listModel=试试!获取(请求)。首先!
    让userList=试试!用户列表(listModel)
    
    
    @objc(UserListModel)
    public class UserListModel: NSManagedObject {
        @NSManaged public var privacy: AccessModel
        @NSManaged public var sharing: AccessModel
        @NSManaged public var someFriendsPrivacy: SomeFriendsPrivacyModel?
        @NSManaged public var someFriendsSharing: SomeFriendsSharingModel?
    }
    
    @objc(SomeFriendsSharingModel)
    public class SomeFriendsSharingModel: NSManagedObject {
        @NSManaged public var ids: [String]
        @NSManaged public var userList: UserListModel
    }
    
    @objc public enum AccessModel: Int32 {
    
        case `public` = 0
        case friendsOnly = 1
        case someFriends = 2
        case `private` = 3
    
    }
    
    {"privacy":"friendsOnly",
    "sharing":{
        "some_friends":
              {"ids":["id1","id2"]}
        }
    }
    
    extension UserList: Codable {}
    
    enum AccessCodableError: Error {
        case error(String)
    }
    
    extension Access: Codable {
    
        enum CodingKeys: String, CodingKey {
            case someFriends
        }
    
        enum NestedKeys: String, CodingKey {
            case ids
        }
    
        var rawValue: String {
            switch self {
            case .friendsOnly:
                return "friendsOnly"
            case .private:
                return "private"
            case .public:
                return "public"
            case .someFriends:
                return "someFriends"
            }
        }
    
        init(from decoder: Decoder) throws {
            if let container = try? decoder.container(keyedBy: CodingKeys.self) {
                let nestedContainer = try container.nestedContainer(keyedBy: NestedKeys.self, forKey: .someFriends)
                let ids = try nestedContainer.decode([String].self, forKey: .ids)
                self = .someFriends(ids: ids)
            }
            else {
                let container = try decoder.singleValueContainer()
                let accessValue = try container.decode(String.self)
                switch accessValue {
                case let value where value == Access.private.rawValue:
                    self = .private
                case let value where value == Access.friendsOnly.rawValue:
                    self = .friendsOnly
                case let value where value == Access.public.rawValue:
                    self = .public
    
                default:
                    throw AccessCodableError.error("Can't determine the decodable key")
                }
            }
    
        }
    
        func encode(to encoder: Encoder) throws {
            switch self {
            case .private, .friendsOnly, .public:
                var container = encoder.singleValueContainer()
                try container.encode(self.rawValue)
            case .someFriends(let userIds):
                var container = encoder.container(keyedBy: CodingKeys.self)
    
                var nestedContainer = container.nestedContainer(keyedBy: NestedKeys.self, forKey: .someFriends)
                try nestedContainer.encode(userIds, forKey: .ids)
            }
        }
    
    }
    
    
    // Encode
    let userList1 = UserList(privacy: .friendsOnly, sharing: .someFriends(ids: ["id1", "id2"]))
    let encoder = JSONEncoder()
    encoder.keyEncodingStrategy = .convertToSnakeCase
    let json = try! encoder.encode(userList1) 
    // Decode
    let decoder = JSONDecoder()
    decoder.keyDecodingStrategy = .convertFromSnakeCase
    let decodedList = try! decoder.decode(UserList.self, from: json)
    
    
    
    extension Access {
        var ids: [String]? {
            switch self {
            case .someFriends(let ids):
                return ids
            default:
                return nil
            }
        }
    }
    
    extension CodingUserInfoKey {
        static let context = CodingUserInfoKey(rawValue: "context")!
    }
    
    @objc(UserListModel)
    public class UserListModel: NSManagedObject, Decodable {
    
        enum CodingKeys: String, CodingKey {
            case privacy
            case sharing
        }
    
        required convenience public init(from decoder: Decoder) throws {
            guard let context = decoder.userInfo[.context] as? NSManagedObjectContext
                else { throw NSError() }
            self.init(context: context)
            let container = try decoder.container(keyedBy: CodingKeys.self)
            let privacy = try container.decode(Access.self, forKey: .privacy)
            let sharing = try container.decode(Access.self, forKey: .sharing)
    
            self.privacy = AccessModel(privacy)
            self.sharing = AccessModel(sharing)
    
            if let ids = privacy.ids {
                let model = SomeFriendsPrivacyModel(context: context)
                model.ids = ids
                model.userList = self
                someFriendsPrivacy = model
            }
    
            if let ids = sharing.ids {
                let model = SomeFriendsSharingModel(context: context)
                model.ids = ids
                model.userList = self
                someFriendsSharing = model
            }
    
        }
    
    }
    
    
            let appDelegate = UIApplication.shared.delegate as! AppDelegate
            let context = appDelegate.persistentContainer.viewContext
            let decoder = JSONDecoder()
            decoder.keyDecodingStrategy = .convertFromSnakeCase
            decoder.userInfo[.context] = context
            try! decoder.decode(UserListModel.self, from: json) // json from 1 question
            try! context.save()
    
    extension Access {
        init?(_ accessModel: AccessModel) {
            switch accessModel {
            case .friendsOnly:
                self = .friendsOnly
            case .private:
                self = .private
            case .public:
                self = .public
            default:
                return nil
            }
        }
    }
    
    enum UserListInitError: Error {
        case error(String)
    }
    
    extension UserList {
    
        init(_ listModel: UserListModel) throws {
            if let privacy = Access(listModel.privacy) {
                self.privacy = privacy
            } else {
                guard let ids = listModel.someFriendsPrivacy?.ids else { throw UserListInitError.error("Unable to get data from Core Data model") }
                self.privacy = .someFriends(ids: ids)
            }
    
            if let sharing = Access(listModel.sharing) {
                self.sharing = sharing
            } else {
                guard let ids = listModel.someFriendsSharing?.ids else { throw UserListInitError.error("Unable to get data from Core Data model") }
                self.sharing = .someFriends(ids: ids)
            }
        }
    }
    
    
            let appDelegate = UIApplication.shared.delegate as! AppDelegate
            let context = appDelegate.persistentContainer.viewContext
            let request: NSFetchRequest<UserListModel> = UserListModel.fetchRequest()
            let listModel = try! context.fetch(request).first!
            let userList = try! UserList(listModel)