尝试在原型上调用函数时EXC_BAD_ACCESS

时间:2018-01-23 17:00:35

标签: swift swift-protocols

这是我遇到的一个有趣的快速问题。请考虑以下类和协议:

class Person {

}

protocol Parent where Self: Person {
    func speak()
}

class GrandMotherPerson: Person, Parent {
    func speak() {
        print("I am a Grandmother Person")
    }
}

class GrandFatherPerson: Person, Parent {
    func speak() {
        print("I am a Grandfather Person")
    }
}

let gmp = GrandMotherPerson()
let gfp = GrandFatherPerson()

现在打电话

gmp.speak() // Output: I am a Grandmother Person
gfp.speak() // Output: I am a Grandfather Person

但是如果你转向父母

(gmp as Parent).speak() // EXC_BAD_ACCESS when it should say "I am a Grandmother Person"

但是如果我print(String(describing: gmp))它说它是__lldb_expr_226.GrandMotherPerson

为什么不能在课堂上快速拨打speak?如果从协议中删除where Self: Person,则它会按预期工作。

1 个答案:

答案 0 :(得分:6)

我很确定这是在https://bugs.swift.org/browse/SR-55详细讨论的同一个深层问题。考虑一下这个编译并运行得很好:

class Person : NSObject {}
@objc protocol Parent where Self: Person {
    func speak()
}
class GrandMotherPerson: Person, Parent {
    func speak() {
        print("I am a Grandmother Person")
    }
}
let gmp = GrandMotherPerson()
let parent = gmp as Parent
parent.speak() // I am a Grandmother Person

但现在删除@objc,我们遇到了同样的问题:

class Person : NSObject {}
protocol Parent where Self: Person {
    func speak()
}
class GrandMotherPerson: Person, Parent {
    func speak() {
        print("I am a Grandmother Person")
    }
}
let gmp = GrandMotherPerson()
let parent = gmp as Parent
parent.speak() // EXC_BAD_ACCESS

因此,如果是同一个问题,Swift团队非常了解它,但它运行得很深,难以修复。现在的解决方法是在我的第一个示例中使用@objc

注意我故意将您的最后一个声明分成两部分。那是因为说(gmp as Parent).speak()似乎还有一个问题 - 显然我们需要一个对存在主义而不是隐含临时性的实际变量引用。