使用 EXC_BAD_INSTRUCTION 在空扩展中断中声明符合 @objc 协议 [英] Declaring conformance to @objc protocol in empty extension breaks with EXC_BAD_INSTRUCTION

查看:55
本文介绍了使用 EXC_BAD_INSTRUCTION 在空扩展中断中声明符合 @objc 协议的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

将 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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆