我正在尝试制作一个Actor
类和一个Movie
类,这些类可以从JSON文件中进行解码。还有一个字典allActors
,其中包含每个Actor
实例,以便解码的每个电影都引用相同的Actor
实例。同样,当将Actor
添加到Movie
的{{1}}数组时,cast
将附加到Movie
的{{1}}数组中。这是我到目前为止的代码:
Actor
此代码有效,但是,在filmography
的{{1}}初始化程序的第四行,public var allActors = [String: Actor]()
public final class Actor {
public let name: String
public var filmography: [Movie]
public init(name: String, filmography: [Movie] = Array()) {
self.name = name
self.filmography = filmography
}
}
public final class Movie: Codable {
public let title: String
public var cast: [Actor]
enum CodingKeys: String, CodingKey {
case title
case cast
}
public init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
title = try values.decode(String.self, forKey: .title)
cast = Array() // fourth line of this initializer
cast = try values.decode([String].self, forKey: .cast).map {
let actor: Actor
if let recurringActor = allActors[$0] {
actor = recurringActor
} else {
let newActor = Actor(name: $0)
allActors[$0] = newActor
actor = newActor
}
actor.filmography.append(self)
return actor
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(title, forKey: .title)
try container.encode(cast.map {$0.name}, forKey: .cast)
}
}
被设置为空数组。这似乎是多余的,但是如果删除它,则会出现以下错误:
在初始化所有成员之前,闭包捕获了
有没有办法可以避免此错误?我没有使用Movie
的任何属性,所以我看不到为什么不能在闭包中使用init(from:)
的引用。
答案 0 :(得分:2)
你不能说
actor.filmography.append(self)
直到self
被完全初始化。在其cast
属性具有值之前,不会发生这种情况。 (当然,还有其他所有属性。)这充分解释了这种现象。
答案 1 :(得分:0)
这不是您问题的直接答案,但是您可以简单地将电影解码,将其简化为字典并将其键/值对映射到actor数组中:
struct Movie: Codable {
let title: String
let cast: [String]
}
struct Actor: CustomStringConvertible {
let name: String
let filmography: [String]
var description: String { "Name: \(name) - Movies: \(filmography)" }
}
游乐场测试:
let movies = try! JSONDecoder().decode([Movie].self, from: Data(json.utf8))
let actors = movies.reduce(into: [:]) { dict, movie in
for name in movie.cast {
dict[name, default: []].append(movie.title)
}
}.map(Actor.init)
print(actors)
这将打印:
[名称:凯文·培根-电影:[“晚餐”,“脚步声”,“平底锅”], 姓名:马克·鲁法洛-电影:[“ Spotlight”],姓名:约翰·拉芙琳- 电影:[“ Footloose”],名称:贝丝·格兰特-电影:[“ Flatliners”], 名称:Liev Schreiber-电影:[“ Spotlight”],名称:John Slattery- 电影:[“ Spotlight”],名称:Paul Guilfoyle-电影:[“ Spotlight”], 名称:Len Cariou-电影:[“ Spotlight”],名称:Neal Huff-电影: [“ Spotlight”],名称:Colette Blonigan-电影:[“ Diner”],名称: 弗朗西丝·李·麦凯恩(Frances Lee McCain)-电影:[“ Footloose”],名字:黛安·维斯特(Dianne Wiest)- 电影:[“ Footloose”],名称:艾伦·巴金-电影:[“ Diner”],名称: 迈克尔·塔克(Michael Tucker)-电影:[“晚餐”],名称:蕾切尔·麦克亚当斯-电影: [“ Spotlight”],名称:Joshua Rudoy-电影:[“ Flatliners”],名称: Jamey Sheridan-电影:[“ Spotlight”],名称:Patricia Belcher- 电影:[“ Flatliners”],名称:Stanley Tucci-电影:[“ Spotlight”], 名称:Hope Davis-电影:[“ Flatliners”],名称:Maureen Keiller- 电影:[“ Spotlight”],名称:蒂姆·戴利-电影:[“ Diner”],名称:比利 Crudup-电影:[《吃祈祷的爱》,《 Spotlight》],名称:史蒂夫 古腾堡-电影:[“晚餐”],名称:哈迪·苏比扬托-电影:[“吃 祈祷爱”],名称:Mike O'Malley-电影:[“吃祈祷爱”],名称: Brian d'Arcy James-电影:[“ Spotlight”],名称:Gene Amoroso- 电影:[“ Spotlight”],名称:Rushita Singh-电影:[“ Eat Pray 爱”],名称:朱莉娅·罗伯茨-电影:[“平底鞋”,“吃祈祷爱”], 名称:基弗·萨瑟兰-电影:[“ Flatliners”],名称:克莱门特·福勒 -电影:[“晚餐”],名称:迈克尔·西里尔·克里顿(Michael Cyril Creighton)-电影:[“ Spotlight”],名称:金伯利·斯科特-电影:[“ Flatliners”],名称: 维奥拉·戴维斯(Viola Davis)-电影:[“ Eat Pray Love”],名字:索菲·汤普森- 电影:[“ Eat Pray Love”],名称:哈维尔·巴尔德姆(Javier Bardem)-电影:[“ Eat Pray 爱”],名字:图瓦·诺沃特尼-电影:[“ Eat Pray Love”],名字:约翰 Lithgow-电影:[“ Footloose”],名称:Laurie Heineman-电影: [“ Spotlight”],名称:Tim Progosh-电影:[“ Spotlight”],名称:阿琳 Tur-电影:[“ Eat Pray Love”],名字:Lynne Marta-电影: [“ Footloose”],名称:Jim Youngs-电影:[“ Footloose”],名称:Daniel 斯特恩-电影:[“晚餐”],名字:詹姆斯·佛朗哥-电影:[“吃祈祷 爱”],名称:吉塔·雷迪-电影:[“ Eat Pray Love”],名称:杰西卡 詹姆斯-电影:[“ Diner”],名称:Kelle Kipp-电影:[“ Diner”],名称: 克里斯汀·哈基姆(Christine Hakim)-电影:[[Eat Pray Love]],名字:道格拉斯·迪尔克森(Douglas Dirkson)- 电影:[“ Footloose”],名称:凯思琳·道林(Kathryn Dowling)-电影:[“ Diner”], 名称:威廉·鲍德温-电影:[“平底鞋”],名称:本杰明·木顿 -电影:[“ Flatliners”],名称:莎拉·杰西卡·帕克-电影:[“ Footloose”],名称:Lori Singer-电影:[“ Footloose”],名称:保罗 Reiser-电影:[“ Diner”],名称:Chris Penn-电影:[“ Footloose”], 名称:奥利弗·普拉特(Oliver Platt)-电影:[“ Flatliners”],名称:迈克尔·基顿- 电影:[“ Spotlight”],名称:Mickey Rourke-电影:[“ Diner”],名称: 克劳迪娅·克朗(Claudia Cron)-电影:[“晚餐”],名称:理查德·詹金斯-电影: [“ Eat Pray Love”,“ Spotlight”],名称:Luca Argentero-电影:[“ Eat 祈祷爱“]]