在闭包中使用数组时的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也是垃圾,返回一个随机数大,如232521760arr自身指向某个遥远的地方周围0xfffffff9,显然这意味着它的垃圾。

我的问题是为什么呢?编译器不会抱怨类型错误。为什么我不能使用该myArr数组,编译器myArr在离开闭包后是否会取消分配?

我可以通过将provider通话更改为:

provider({ (myArr : [AnyObject]) -> () in
    for e in myArr{
      self.arr.append(e as MyObj)
    }
    self.didRun = true
 })

但是我对为什么我的第一个代码不起作用更感兴趣。

如果有人可以向我解释Swift中的闭包语义以及为什么上面的代码会产生此类错误,我将不胜感激。

阿卡西夫斯基

编辑:@SevenTenEleven(Apple员工)在与此问题相关ADF线程指出的

似乎某些协变数组分配存在问题;请提交错误,以便我们可以在编译时正确禁止它们或在运行时正确实现它们。

我们做到了,我做到了


经过一些实验研究,我得出以下结论:

  • 这与clousures和外部范围无关
  • 仅当您向下转换[AnyObject][MyObj]
  • 仅当将“外部”变量声明为协议类型数组时,错误才会发生

由于似乎provider总是会返回Testable,因此我可以通过更改provider函数声明并将a变量明确标记为以下数组来使代码正常工作Testable

func provider(cb: [Testable] -> ()) {
    let a : [Testable] = [MyObj(), 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(), MyObj()]
        cb(a)
    }
}

let t = Test()
t.run()
t.run()

前面的代码输出:

arr has 3 elements
_TtC5hgfds5MyObj
_TtC5hgfds5MyObj
_TtC5hgfds5MyObj

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

使用NativeCSS时EXC_BAD_ACCESS

来自分类Dev

UIAlertController EXC_BAD_ACCESS错误-Swift

来自分类Dev

Swift中的UIWebView:exc_bad_access

来自分类Dev

Swift:animator()导致EXC_BAD_ACCESS

来自分类Dev

Swift中的UIDocumentInteractionControllerDelegate EXC_BAD_ACCESS

来自分类Dev

Swift中的UIWebView:exc_bad_access

来自分类Dev

生成nspredicate时EXC_BAD_ACCESS

来自分类Dev

执行块时EXC_BAD_ACCESS

来自分类Dev

EXC_BAD_ACCESS 执行关闭时

来自分类Dev

使用协议组成的EXC_BAD_ACCESS

来自分类Dev

使用MPMoviePlayerViewController的EXC_BAD_ACCESS

来自分类Dev

使用数组C ++时的“ EXC_BAD_ACCESS”

来自分类Dev

Swift:观察NSUserDefaults时为EXC_BAD_ACCESS

来自分类Dev

使用object_setIvar时为EXC_BAD_ACCESS

来自分类Dev

使用cfnetwork写入输出流时,exc_bad_access

来自分类Dev

使用泛型时为EXC_BAD_ACCESS

来自分类Dev

使用scrollViewDidScroll时出错EXC_BAD_ACCESS

来自分类Dev

在代码中添加UINavigationController时使用EXC_BAD_ACCESS

来自分类Dev

Swift dispatch_async导致EXC_BAD_ACCESS错误

来自分类Dev

Swift字符串操作导致EXC_BAD_ACCESS

来自分类Dev

Swift:glDrawElements崩溃,代码为EXC_BAD_ACCESS = 1

来自分类Dev

NSManagedObject在Swift中实现协议的EXC_BAD_ACCESS错误

来自分类Dev

Swift中的UIAlertView,获取EXC_BAD_ACCESS

来自分类Dev

Swift中的parser.parse()导致EXC_BAD_ACCESS

来自分类Dev

Swift中的泛型和EXC_BAD_ACCESS

来自分类Dev

在Swift 2.1的Spritekit游戏中获取EXC_BAD_ACCESS

来自分类Dev

Swift子类化UITableViewDataSource EXC_BAD_ACCESS

来自分类Dev

NSManagedObject在Swift中实现协议的EXC_BAD_ACCESS错误

来自分类Dev

Swift中的泛型和EXC_BAD_ACCESS