Swift ARC和块

时间:2014-08-12 00:49:18

标签: ios swift automatic-ref-counting

我尝试了一个简单的例子,如下所示: https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html#//apple_ref/doc/uid/TP40014097-CH20-XID_88

这是我的代码。 (忽略其他可能的代码,这是一个空项目,此代码写在一个空的UIViewcontroller viewDidLoad中)

    dispatch_async(dispatch_get_main_queue()) {
        [unowned self] in
        println(self)
    }

我不明白为什么在我运行专业人员时会崩溃

  
      
  • 线程#1:tid = 0x1a796,0x00284d18 libswiftCore.dylib`_swift_release_slow + 8,queue =   ' com.apple.main-thread',停止原因= EXC_BAD_ACCESS(代码= 1,   地址= 0x458bc681)
  •   

最新的测试版(5)发生了什么变化,这是不再支持的了? 感谢

编辑: 有趣的是这段代码适用于Objc

__weak MyViewController *weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
    NSLog(@"%@", weakSelf);
});

EDIT2: 关于这个链接的解释:Shall we always use [unowned self] inside closure in Swift关于弱者和无人的差异是错误的。

不仅仅是那些弱小的无所事事并没有。如果是这样的话,那也应该崩溃:

  dispatch_async(dispatch_get_main_queue()) {
            [weak self] in
            println(self)
        }

但它没有,它打印指针,因此,它不是零。

1 个答案:

答案 0 :(得分:9)

[Unowned self]使得闭包不会创建对self的强引用,如果它也被解除分配,它也不会自动将其设置为nil。到异步方法执行时,self已被释放。这就是你遇到崩溃的原因。

在一次性异步调用中使用unowned当然没有意义。最好是抓住它的强有力的参考,以确保它坚持下去。仍然没有成为一个强大的参考周期,因为self不拥有闭包。

旁注:这不是您的所有代码,因为self未在代码中的任何位置定义。

unownedweak是两回事。在Objective-C中,unowned被称为unsafe unretained。您可以在两种语言中使用weakweak表示如果取消分配对象,运行时将自动将引用转换为nilunownedunsafe unretained表示它不会被设置为nil(这就是为什么它被称为"不安全"在Objective-C中。

Unowned只应在永远不会释放对象的情况下使用。在这种情况下,请使用weak

请记住,如果你在Swift中将变量捕获为weak,那么引用将是可选的,因此要使用它,你必须打开它:

dispatch_async(dispatch_get_main_queue()) {
    [weak self] in
    if let actualSelf == self {
         // do something with actualSelf
    }
    // you can still print the "wrapped" self because it is fine to print optionals
    // even if they are `nil`
    println(self)
}

但要明确的是,在这种情况下使用强引用仍然是最好的:

dispatch_async(dispatch_get_main_queue()) {
    println(self)
}