问题
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.
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
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.
- 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
{}
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.
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"}
回答1:
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 {}
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.
来源:https://stackoverflow.com/questions/28131121/declaring-conformance-to-objc-protocol-in-empty-extension-breaks-with-exc-bad-i