Swift-为什么在初始化所有存储的属性之前不能在闭包中使用self?

时间:2019-12-29 22:51:01

标签: swift oop closures self

我正在尝试制作一个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:)的引用。

2 个答案:

答案 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   祈祷爱“]]