使用可编码保存到 CoreData 字符串数组



我被困住了。 我有json(电影数组(。我正在尝试使用可编码协议解析它,并保存到核心数据。 问题是电影对象具有流派数组(字符串数组(。我创建了两个实体:电影和流派(具有一对多的关系(。解析电影对象没有问题,但是当我尝试解析流派时 - 它不起作用。

知道吗?

附言是的,我知道流派数组没有键"名称"。

{
"title": "Dawn of the Planet of the Apes",
"image": "https://api.androidhive.info/json/movies/1.jpg",
"rating": 8.3,
"releaseYear": 2014,
"genre": ["Action", "Drama", "Sci-Fi"]
},
{
"title": "District 9",
"image": "https://api.androidhive.info/json/movies/2.jpg",
"rating": 8,
"releaseYear": 2009,
"genre": ["Action", "Sci-Fi", "Thriller"]
}

电影型号:

@objc(Movie)
class Movie: NSManagedObject, Decodable {
@NSManaged var title: String?
@NSManaged var image: String?
@NSManaged var rating: Float
@NSManaged var releaseYear: Int
@NSManaged var genres: Set<Genre>?
enum apiKey: String, CodingKey {
case title
case image
case rating
case releaseYear
case genres = "genre"
}
@nonobjc public class func request() -> NSFetchRequest<Movie> {
return NSFetchRequest<Movie>(entityName: "Movie")
}
// MARK: - Decodable
public required convenience init(from decoder: Decoder) throws {
guard let contextUserInfoKey = CodingUserInfoKey.context,
let manageObjContext = decoder.userInfo[contextUserInfoKey] as? NSManagedObjectContext,
let manageObjMovie = NSEntityDescription.entity(forEntityName: "Movie", in: manageObjContext) else {
fatalError("Error to getting context")
}
self.init(entity: manageObjMovie, insertInto: manageObjContext)
let container = try decoder.container(keyedBy: apiKey.self)
self.title = try container.decodeIfPresent(String.self, forKey: .title)
self.image = try container.decodeIfPresent(String.self, forKey: .image)
self.rating = try container.decodeIfPresent(Float.self, forKey: .rating) ?? 0
self.releaseYear = try container.decodeIfPresent(Int.self, forKey: .releaseYear) ?? 0
self.genres = try container.decodeIfPresent(Set<Genre>.self, forKey: .genres) ?? []        
}
}
// MARK: Generated accessors for geonames
extension Movie {
@objc(addGenresObject:)
@NSManaged func addToGenres(_ value: Genre)
@objc(setKeyObject:)
@NSManaged func setKeyObject(_ value: String)
}

流派模型:

@objc(Genre)
class Genre: NSManagedObject, Decodable {
@NSManaged var name: String?
enum apiKey: String, CodingKey {
case name
}
@nonobjc public class func request() -> NSFetchRequest<Genre> {
return NSFetchRequest<Genre>(entityName: "Genre")
}
// MARK: - Decodable
public required convenience init(from decoder: Decoder) throws {
guard let contextUserInfoKey = CodingUserInfoKey.context,
let manageObjContext = decoder.userInfo[contextUserInfoKey] as? NSManagedObjectContext,
let manageObjGenre = NSEntityDescription.entity(forEntityName: "Genre", in: manageObjContext) else {
fatalError("Error to getting context")
}
self.init(entity: manageObjGenre, insertInto: manageObjContext)
let container = try decoder.container(keyedBy: apiKey.self)
self.name = try container.decodeIfPresent(String.self, forKey: .name)
}
}

您需要一个反比关系才能MovieGenre。添加此

@NSManaged var movie: Movie?

并在模型文件中建立连接。

然后解码一个字符串数组,将其映射到流派实例,并在 init 方法结束时将self分配给该关系

let genreData = try container.decodeIfPresent([String].self, forKey: .genres) ?? []
let genreArray = genreData.map { name in
let genre = Genre(context: manageObjContext)
genre.name = name
genre.movie = self
return genre
}
self.genres = Set(genreArray)

请考虑使用从GenreMovie的对多关系,否则您将有很多同名的Genre实例。并考虑减少核心数据类中的可选项。JSON源似乎始终提供所有字段。您可以摆脱大量冗余代码。

相关内容

  • 没有找到相关文章

最新更新