【问题标题】:Swift class: reference cycleSwift 类:引用循环
【发布时间】:2015-01-03 09:44:08
【问题描述】:

当我运行下面的程序时,它会产生分段错误。你能帮我弄清楚为什么吗?谢谢

class Animal:NSObject{
    var  name:String!
    var age:UInt!

    weak var spouse:Animal?
    init(name:String,age:UInt){
        self.name=name
        self.age=age
    }

    func description() ->String{ //to become printable
        return "name= \(name) and age=\(age) spouse=\(spouse)"
    }
}


let dog=Animal(name:"Lucky",age:3)
let cat=Animal(name:"Branson",age:4)
dog.spouse=cat
cat.spouse=dog //It doesnt crash if I comment this line out
println(dog)

【问题讨论】:

    标签: class swift strong-references


    【解决方案1】:

    问题是打印中的无限递归。一旦你设置了完整的循环,打印一个动物,你打印它的配偶,它打印它的配偶,它打印它的配偶等等,直到你用完堆栈空间并崩溃。

    你需要通过打印出动物的配偶而不调用该动物的完整打印来打破这种情况,如下所示:

    class Animal: NSObject {
        // you should avoid using implicitly unwrapped optionals
        // unless you absolutely have to for a specific reason that
        // doesn’t appear to apply here (so remove the !s)
        var name: String
        var age: UInt
        weak var spouse: Animal?
    
        init(name: String, age: UInt) {
            self.name = name
            self.age = age
        }
    }
    
    // to make something printable, you need to conform
    // to the Printable protocol
    extension Animal: Printable {
        // And make description is a var rather than a function
        override var description: String {
            let spousal_status = spouse?.name ?? "None"
            return "name=\(name) and age=\(age), spouse=\(spousal_status)"
        }
    }
    
    
    let dog = Animal(name: "Lucky", age: 3)
    let cat = Animal(name: "Branson", age: 4)
    dog.spouse = cat
    dog.description
    cat.spouse = dog
    println(dog)  // Prints name=Lucky and age=3, spouse=Branson
    

    注意,您必须使用协议和 var 完全实现 Printable 以避免此问题,否则您将获得默认实现,但仍会遇到此问题。

    顺便说一句,Swift 风格的约定是在=->{ 等之前放置空格(事实上,如果不这样做,有时会导致编译问题)。 a: ba:b 的评判仍在进行中,尽管我发现后者有点难以阅读。

    【讨论】:

    • 非常感谢。我昨天发布了我的错误,并且能够在我的代码中更正它。非常感谢您的反馈。
    • 不客气。只是一个 Stack Overflow 提示——感谢回答你问题的人的方式是接受答案。这有助于其他人看到给出的答案确实回答了问题(无论如何,对你来说——这并不意味着答案是完全正确的:)
    【解决方案2】:

    您的代码触发了堆栈溢出。 description 方法包含spouse 描述,这将依次触发其spouse 的描述,以此类推,循环往复。试试这个:

    func description() -> String {
      return "name= \(name) and age=\(age) spouse=\(spouse?.name)"
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-13
      相关资源
      最近更新 更多