考虑以下玩具示例
Swift代码:
protocol Testable{} class MyObj : Testable{} class Test { var arr:[Testable] = [] var didRun:Bool = false func run() -> [Testable]{ if(didRun){ println("arr has \(arr.count) elements") for e in arr{ // following access causes EXC_BAD_ACCESS println(e) } return arr } else{ provider({ (myArr : [AnyObject]) -> () in self.arr = myArr as [MyObj] self.didRun = true }) return [] } } func provider( cb : ([AnyObject] -> ()) ){ let a:[MyObj] = [MyObj(),MyObj(),MyObj()] cb(a) } }
并按以下方式调用它:
let t = test() t.run() t.run()
这会在尝试迭代返回的数组时编译但在运行时崩溃. arr.count也是垃圾,返回一个随机的大数字,如232521760和arr本身指向远在0xfffffff9附近的某个地方,这意味着它显然是垃圾.
我的问题是为什么会这样?编译器不会抱怨类型错误.为什么我无法使用myArr数组,编译器在离开闭包后是否取消分配myArr?
我可以通过将提供者调用更改为:
provider({ (myArr : [AnyObject]) -> () in for e in myArr{ self.arr.append(e as MyObj) } self.didRun = true })
如果有人可以向我解释Swift中的闭包语义以及为什么上面会产生这样的错误,我将不胜感激.
解决方法
编辑:正如
@SevenTenEleven(苹果员工)
ADF thread related to this question所述:
It looks like there are issues with some covariant array assignments; please file a bug so we can either properly ban them at compile-time or properly implement them at runtime.
我们这样做,I did.
做了一些experiments和research后,我得出以下结论:
>这与clousures和外部范围无关
>只有将[AnyObject]向下转换为[MyObj]时才会发生错误
>只有将“外部”变量声明为协议类型数组时,错误才会出现
由于似乎提供者总是返回Testable,因此我能够通过更改提供者函数声明并将变量显式标记为Testable数组来使代码工作:
func provider(cb: [Testable] -> ()) { let a : [Testable] = [MyObj(),MyObj()] cb(a) }
protocol Testable {} class MyObj : Testable {} class Test { var arr : [Testable] = [] var didRun = false func run() -> [Testable] { if didRun { println("arr has \(arr.count) elements") for e in arr { println(e) } return arr } else { provider() { (myArr : [Testable]) in self.arr = myArr self.didRun = true } return [] } } func provider(cb: [Testable] -> ()) { let a : [Testable] = [MyObj(),MyObj()] cb(a) } } let t = test() t.run() t.run()
arr has 3 elements _TtC5hgfds5MyObj _TtC5hgfds5MyObj _TtC5hgfds5MyObj
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。