使用 EXC_BAD_INSTRUCTION 在空扩展中断中声明符合 @objc 协议 [英] Declaring conformance to @objc protocol in empty extension breaks with EXC_BAD_INSTRUCTION
问题描述
将 Swift 协议与数组结合使用时遇到了很多很多麻烦,但在操场上开始出现问题之前,我什至无法重现我的整个问题.这是一个最小的例子.
Been having lots and lots of trouble with Swift protocols in combination with arrays, but I couldn't even reproduce my whole problem before things started to break in playground. Here's a minimal example.
我有两个协议和一个 Bus
类,它声明符合其中一个协议.此外,Bus
的空扩展声明符合其他协议:
I have two protocols and a class Bus
which declares conformance to one of the protocols. In addition, an empty extension of Bus
declares conformance to the other protocol:
import Foundation
@objc
protocol Displayable { var name: String {get} }
@objc
protocol Utterable { var utterance: String {get} }
class Bus : Displayable { var name = "a bus"; var utterance = "this is a bus"}
extension Bus : Utterable {}
var bus1 = Bus() // this line fails with EXC_BAD_INSTRUCTION
控制台输出可能看起来是随机的,但事实并非如此.如果我尝试创建 Bus
的实例,我会一直得到它:
The console output may look random but it's not. I get it consistently if I try to create an instance of Bus
:
objc[9658]: Method cache corrupted. This may be a message to an invalid object, or a memory error somewhere else.
objc[9658]: unused 0x0, SEL 0x10e4ce130, isa 0x1181f9ad0, cache 0x1181f9ae0, buckets 0x7fc491501060, mask 0x0, occupied 0x0
objc[9658]: unused 0 bytes, buckets 64 bytes
objc[9658]: selector 'resolveInstanceMethod:'
objc[9658]: isa '__lldb_expr_1314.Bus'
objc[9658]: Method cache corrupted.
- 如果我们注释掉所有
@objc
属性,错误就会消失 - 如果我们不符合
Utterable
:extension Bus
: Utterable
{}
- The error goes away if we comment out all
@objc
attributes - The error goes away if we don't conform to
Utterable
:extension Bus
: Utterable
{}
我的协议必须具有@objc
属性的原因是,否则Obj-c运行时会在尝试执行var myDisplayables之类的操作时报错:[Displayable] = [ Bus() ]
或以其他方式动态检查是否符合协议
The reason why my protocols must have the attribute @objc
is because otherwise the Obj-c runtime will complain when trying to do things like var myDisplayables: [Displayable] = [ Bus() ]
or otherwise dynamically check for conformance to a protocol
同样,请注意这是一个最小的例子.
Again, please note that this is a minimal example.
使用 Swift 1.2 更新:现在好像修好了.Xcode 建议进行这些更改,因为协议需要它":
Update with Swift 1.2: Seems like it's fixed now. Xcode suggests these changes "because the protocol requires it":
class Bus : Displayable { @objc var name = "a bus"; @objc var utterance = "this is a bus"}
推荐答案
我认为问题在于 Utterable
协议有一个属性,该属性已经在具体类中实现了.
I think that the problem is about the Utterable
protocol having a property, which is already implemented in the concrete class.
您可能知道,扩展不能定义存储属性(仅计算).通过在扩展中采用协议,会发生错误 - 这显然是一个错误(它应该可以正常工作或编译器应该引发编译错误).
As you probably know, an extension cannot define stored properties (computed only). By adopting the protocol in the extension, something wrong happens - and it is clearly a bug (it should just work or the compiler should raise a compilation error).
要修复它,只需在类声明中采用协议而不是扩展:
To fix it, just adopt the protocol in the class declaration rather than to the extension:
class Bus : Displayable, Utterable { var name = "a bus"; var utterance = "this is a bus"}
extension Bus {}
令人惊讶的是,将 utterance
属性转换为计算属性并将其移动到扩展体中:
Surprisingly, turning the utterance
property into a computed one and moving it in the extension body:
extension Bus : Utterable {
var utterance: String { return "this is a bus" }
}
没有解决问题 - 仍然是同样的错误.我认为这是证明这是一个错误.
doesn't solve the problem - still the same error. I consider it as a prove that it's a bug.
这篇关于使用 EXC_BAD_INSTRUCTION 在空扩展中断中声明符合 @objc 协议的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!