在闭包中使用数组时Swift EXC_BAD_ACCESS
考虑以下玩具示例
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所述:
我们这样做,I did. 做了一些experiments和research后,我得出以下结论: >这与clousures和外部范围无关 由于似乎提供者总是返回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 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- c# – FormsAuthentication.SignOut抛出NullRefe
- (Swift)Missing argument for parameter #1 in c
- jsoncpp 库的使用方法
- c# – 禁用包含WPF中的groupBox名称的groupBox
- C#是否可以将LINQ子句中的orderby抽象为函数参数
- 在Swift中的willSet和didSet的目的是什么?
- swfobject.embedSWF属性与用法
- c# – 使用WebClient.UploadFileAsync方法获取服
- 为你的MacOS App添加开机自启动(Swift)
- ios – 如何在WKWebView历史记录中返回起始点