在 Swift 中使用泛型、协议和继承创建对象时的 EXC_BAD_ACCESS
Posted
技术标签:
【中文标题】在 Swift 中使用泛型、协议和继承创建对象时的 EXC_BAD_ACCESS【英文标题】:EXC_BAD_ACCESS when creating an object with Generics, Protocols and Inheritance in Swift 【发布时间】:2015-01-16 16:57:34 【问题描述】:此代码生成 EXC_BAD_ACCESS(即使在操场上)。
(我简化了代码以便更好地理解。)
准备工作:
// Playground - noun: a place where people can play
protocol EmptyInit
init();
class FirstBase
class SecondBase : EmptyInit
required init()
class A : FirstBase, EmptyInit
required override init()
class B : SecondBase, EmptyInit
required init()
很明显,您可以像这样创建A
和B
的实例。
A();
B();
假设需要在泛型函数中创建一个类的实例:
func creation<T: EmptyInit>(x a:T.Type) -> T
var object = T()
return object;
这段代码运行时:
var b = creation(x: B.self);
此代码因 EXC_BAD_ACCESS 而崩溃
var a = creation(x: A.self);
link to the screenshot of the playground
这很奇怪,不是吗?我不明白。有任何想法吗? (甚至可能是一个 Swift 错误?)
【问题讨论】:
我也放在Apple Dev Forum上。 如果您在 A 类实现中省略“覆盖”会怎样? 不编译。错误消息是:覆盖声明需要一个“覆盖”关键字。 【参考方案1】:更新 Swift 1.2 XCode 6.3 Beta 2(Beta 1 将不起作用): 您的代码现在运行没有任何问题并且得到预期的结果:
var b = creation(x: B.self); //__lldb_expr_9.SecondBase
var a = creation(x: A.self); //__lldb_expr_11.FirstBase
它们发生冲突是因为 FirstBase 没有 init 而 EmptyInit 是必需的 init。 这样它就可以工作了:
protocol EmptyInit
init();
class FirstBase
required init()
class SecondBase : EmptyInit
required init()
class A : FirstBase, EmptyInit
required init()
class B : SecondBase, EmptyInit
required init()
A();
B();
func creation<T: EmptyInit>(x a:T.Type) -> T
var object = T()
return object;
var b = creation(x: B.self); // SecondBase
var a = creation(x: A.self); // FirstBase
【讨论】:
我也遇到了同样的问题 .. 这在可能的情况下解决了 感谢您的回答。你的意思是你的答案是一种解决方法吗?我实际上没有看到 FirstBase 应该实现 init() 的原因。尽管为了避免崩溃 ;-) 我错过了什么吗?FirstBase
必须实现它,因为Class A
应符合协议EmptyInit
。为了符合协议,它必须使用 required
属性实现协议所需的 init。但是它不能,因为它会与它继承的FirstBase
冲突。您不能使用派生自没有 required init
的类的 required init
。
这是有道理的:协议希望确保使用 init。因此,如果一个类想要符合协议和这个 init 要求,它必须实现那个 init。如果它现在也派生自另一个类,那么您必须确保该类也使用这个必需的初始化程序。否则,您无法确保使用了 init。
抱歉不理解 :-) 但是如果 FirstBase 类不在您的控制之下怎么办。这是否意味着如果它不符合协议,您就不能从该类继承?那么协议需要在继承层次上上下实现?【参考方案2】:
得到苹果的答复:
“我们相信这个问题已经在最新的 Xcode 6.3 beta 2 中得到解决,包括带有 Swift 1.2 的 ios 8.3 SDK。”
无法更新自动取款机。将检查(可能在 VM 中)然后再次发布更新。
Alex 对其进行了测试。苹果似乎修复了这个错误。谢谢亚历克斯
【讨论】:
以上是关于在 Swift 中使用泛型、协议和继承创建对象时的 EXC_BAD_ACCESS的主要内容,如果未能解决你的问题,请参考以下文章