Как сохранить пользовательский тип в CoreData с Codable Protocol Swift - PullRequest
0 голосов
/ 01 февраля 2019

Я пытаюсь сохранить пользовательский объект типа codable, в котором я могу хранить тип Int16.Но для типа [Movie] в Coredata его NSObject, Entity I имеет атрибут movie типа Transformable.

Ошибка: кандидаты 'decodeIfPresent' не дают ожидаемый контекстный тип результата 'NSObject?'

Как сохранить этот пользовательский тип Array с типом Transformable

class MovieResults: Results, Codable {

        required convenience public init(from decoder: Decoder) throws  {
            guard let codingUserInfoKeyManagedObjectContext = CodingUserInfoKey.context,
                let managedObjectContext = (UIApplication.shared.delegate as? AppDelegate)?.persistentContainer.viewContext,
                let entity = NSEntityDescription.entity(forEntityName: "Results", in: managedObjectContext) else {
                    fatalError("Failed to retrieve managed object context")
            }

            self.init(entity: entity, insertInto: managedObjectContext)

            let container = try decoder.container(keyedBy: CodingKeys.self)

            self.page = try container.decodeIfPresent(Int16.self, forKey: .page) ?? 0
            self.numberOfResults = try container.decodeIfPresent(Int16.self, forKey: .numberOfResults) ?? 0
            self.numberOfPages = try container.decodeIfPresent(Int16.self, forKey: .numberOfPages) ?? 0
            self.movies = try container.decodeIfPresent([Movie].self, forKey: .movies) ?? nil
        }

        // MARK: - Encodable
        public func encode(to encoder: Encoder) throws {
            var container = encoder.container(keyedBy: CodingKeys.self)
            try container.encode(page, forKey: .page)
            try container.encode(numberOfResults, forKey: .numberOfResults)
            try container.encode(numberOfPages, forKey: .numberOfPages)
            try container.encode(movies, forKey: .movies)
        }

        private enum CodingKeys: String, CodingKey {
            case page
            case numberOfResults = "total_results"
            case numberOfPages = "total_pages"
            case movies = "results"
        }
    }

Массив Movie - это пользовательский атрибут типа Transformable в CoreData

class Movies: Movie, Codable {
    public func encode(to encoder: Encoder) throws {

    }

    required convenience init(from decoder: Decoder) throws {
        guard let codingUserInfoKeyManagedObjectContext = CodingUserInfoKey.context,
            let managedObjectContext = decoder.userInfo[codingUserInfoKeyManagedObjectContext] as? NSManagedObjectContext,
            let entity = NSEntityDescription.entity(forEntityName: "Movie", in: managedObjectContext) else {
                fatalError("Failed to decode User")
        }

        self.init(entity: entity, insertInto: managedObjectContext)

        let container = try decoder.container(keyedBy: CodingKeys.self)

        self.identifier = try container.decodeIfPresent(Int16.self, forKey: .identifier) ?? 0
        self.posterPath = try container.decodeIfPresent(String.self, forKey: .identifier)
        self.backdrop = try container.decodeIfPresent(String.self, forKey: .identifier)
        self.title = try container.decodeIfPresent(String.self, forKey: .identifier)
        self.releaseDate = try container.decodeIfPresent(String.self, forKey: .identifier)
        self.rating = try container.decodeIfPresent(Int16.self, forKey: .rating) ?? 0
        self.overview = try container.decodeIfPresent(String.self, forKey: .identifier)
    }

    enum CodingKeys: String, CodingKey {
        case identifier
        case posterPath = "poster_path"
        case backdrop = "backdrop_path"
        case title
        case releaseDate = "release_date"
        case rating = "vote_average"
        case overview
    }
}

При этом все работает нормально.

self.movies = try container.decodeIfPresent([Movies].self, forKey: .movies)! as NSObject

Я наследую класс NSManagedObject. Это правильный путь.Я пытался использовать расширение, но оно выдает ошибку для инициализаторов .?

public convenience init(from decoder: Decoder) throws

Требование инициализатора 'init (from :)' может быть удовлетворено только 'обязательным' инициализатором вопределение не финального класса MovieResult

1 Ответ

0 голосов
/ 04 февраля 2019

Я думаю, что это можно сделать более простым способом.Вот как вы можете попробовать.Вот класс MovieResult [Хорошо иметь имя класса в единственном числе].

открытый класс MovieResult: Codable {public var stringVariable: String public var intVariable: Int

public init(stringVariable: String, intVariable: Int) {
    self.stringVariable = stringVariable
    self.intVariable = intVariable
}

}

Здесь вы можете сохранить MovieResult in UserDefaults.

public var savedMovieResult: MovieResult? {
    get {
        let data = UserDefaults.standard.object(forKey: "savedMovieResultKey") as? Data
        var movieResult: MovieResult?
        if let data = data {
            do {
                movieResult = try PropertyListDecoder().decode(MovieResult.self, from: data)
            } catch {
                print(error)
            }
        }
        return movieResult
    } set {
        do {
            try UserDefaults.standard.set(PropertyListEncoder().encode(newValue), forKey: "savedMovieResultKey")
            UserDefaults.standard.synchronize()
        } catch {
            print(error)
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...