【问题标题】:Swift - Why can't self be used in a closure before all stored properties are initialized?Swift - 为什么在初始化所有存储属性之前不能在闭包中使用 self ?
【发布时间】:2020-04-18 19:06:33
【问题描述】:

我正在尝试创建一个 Actor 类以及一个可以从 JSON 文件解码的 Movie 类。还有一个字典,allActors,包含每个Actor 实例,因此每部解码的电影都引用相同的Actor 实例。此外,当Actor 添加到Moviecast 数组时,Movie 将附加到Actorfilmography 数组。这是我到目前为止的代码:

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)
    }
}

但是,此代码有效,但在 Movieinit(from:) 初始化程序的第四行,cast 设置为空数组。这似乎是多余的,但如果我删除它,我会收到以下错误:

在所有成员初始化之前被闭包捕获的'self'

有没有办法避免这个错误?我没有使用self 的任何属性,所以我不明白为什么不能在闭包中使用Movie 的引用。

【问题讨论】:

  • allActors 是在哪里声明的?你能发布你的 JSON 字符串吗?
  • 你可以简单地用一个空数组初始化你的castvar cast: [Actor] = []
  • @LeoDabus allActors 声明在代码围栏的顶部。 JSON 文件在这里:pastebin.com/XjGD5q2g

标签: swift oop closures self


【解决方案1】:

不是您问题的直接答案,但您可以简单地解码您的电影,将其缩减为字典并将其键/值对映射到您的演员数组:

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)

这将打印:

[姓名:Kevin Bacon - 电影:[“Diner”、“Footloose”、“Flatliners”], 姓名:Mark Ruffalo - 电影:[“Spotlight”],姓名:John Laughlin - 电影:[“Footloose”],名称:Beth Grant - 电影:[“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”],姓名:Ellen Barkin - 电影:[“Diner”],姓名: Michael Tucker - 电影:[“Diner”],姓名:Rachel McAdams - 电影: [“Spotlight”],姓名:Joshua Rudoy - 电影:[“Flatliners”],姓名: Jamey Sheridan - 电影:[“Spotlight”],姓名:Patricia Belcher - 电影:[“Flatliners”],名称:Stanley Tucci - 电影:[“Spotlight”], 姓名:Hope Davis - 电影:[“Flatliners”],姓名:Maureen Keiller - 电影:[“Spotlight”],姓名:Tim Daly - 电影:[“Diner”],姓名:Billy Crudup - 电影:[“Eat Pray Love”、“Spotlight”],姓名:Steve Guttenberg - 电影:["Diner"],名称:Hadi Subiyanto - 电影:["Eat Pray Love"],姓名:Mike O'Malley - 电影:["Eat Pray Love"],姓名: Brian d'Arcy James - 电影:[“Spotlight”],姓名:Gene Amoroso - 电影:[“Spotlight”],名称:Rushita Singh - 电影:[“Eat Pray” 爱”],姓名:朱莉娅·罗伯茨 - 电影:[“Flatliners”,“吃祈祷爱”], 姓名:Kiefer Sutherland - 电影:[“Flatliners”],姓名:Clement Fowler - 电影:["Diner"],姓名:Michael Cyril Creighton - 电影:["Spotlight"],姓名:Kimberly Scott - 电影:["Flatliners"],姓名: Viola Davis - 电影:[“Eat Pray Love”],姓名:Sophie Thompson - 电影:[“Eat Pray Love”],名称:Javier Bardem - 电影:[“Eat Pray” Love"],姓名:Tuva Novotny - 电影:["Eat Pray Love"],姓名:John Lithgow - 电影:[“Footloose”],姓名:Laurie Heineman - 电影: [“Spotlight”],姓名:Tim Progosh - 电影:[“Spotlight”],姓名:Arlene Tur - 电影:[“Eat Pray Love”],姓名:Lynne Marta - 电影: [“Footloose”],姓名:Jim Youngs - 电影:[“Footloose”],姓名:Daniel Stern - 电影:[“Diner”],姓名:James Franco - 电影:[“Eat Pray” Love"],姓名:Gita Reddy - 电影:["Eat Pray Love"],姓名:Jessica 詹姆斯 - 电影:[“Diner”],姓名:Kelle Kipp - 电影:[“Diner”],姓名: Christine Hakim - 电影:[“Eat Pray Love”],姓名:Douglas Dirkson - 电影:[“Footloose”],名称:Kathryn Dowling - 电影:[“Diner”], 姓名:威廉·鲍德温 - 电影:[“Flatliners”],姓名:本杰明·穆顿 - 电影:[“Flatliners”],姓名:Sarah Jessica Parker - 电影:[“Footloose”],姓名:Lori Singer - 电影:[“Footloose”],姓名:Paul Reiser - 电影:[“Diner”],姓名:Chris Penn - 电影:[“Footloose”], 姓名:奥利弗·普拉特 - 电影:[“Flatliners”],姓名:迈克尔·基顿 - 电影:[“Spotlight”],名称:Mickey Rourke - 电影:[“Diner”],名称: Claudia Cron - 电影:[“Diner”],姓名:Richard Jenkins - 电影: [“Eat Pray Love”、“Spotlight”],名称:Luca Argentero - 电影:[“Eat 祈祷爱”]]

【讨论】:

    【解决方案2】:

    你不能说

    actor.filmography.append(self)
    

    直到self 完全初始化。直到它的 cast 属性有值才会发生这种情况。 (当然还有它的所有其他属性。)这完全解释了这种现象。

    【讨论】:

      猜你喜欢
      • 2016-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-09
      相关资源
      最近更新 更多