【问题标题】:Swift ARC and blocksSwift ARC 和块
【发布时间】:2014-10-04 22:46:47
【问题描述】:

我正在尝试一个简单的示例,如下所示: 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)
    }

我不明白为什么我运行 pro 时它会崩溃

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

最新的 beta(5) 是否发生了变化并且不再支持? 谢谢

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

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

编辑2: 这个链接上的解释:Shall we always use [unowned self] inside closure in Swift关于弱和无主的区别是错误的。

不仅仅是weak nils 和unowned 没有。如果是这种情况,这也应该崩溃:

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

但它没有,它打印指针,所以它不是 nil。

【问题讨论】:

  • 来自The Swift Programming Language:“如果在释放它引用的实例后尝试访问无主引用,则会触发运行时错误。”
  • Unowned 表示 self 没有被保留,但是如果 self 被释放并使用了 unowned,那么你将会崩溃。如果它可能会被释放,则使用强或弱。
  • 您最后的评论 [weak self] 应该导致崩溃是不正确的。 self 在这种情况下是可选的。您应该期望上面打印nil 或类似的东西。 unowned 的意思是“我发誓它不会是零,如果是的话,让我崩溃。” weak 的意思是“它是可选的,所以nil 是可以接受的。”
  • @RobNapier 并不是说​​它不会崩溃,而是它还会打印指针值,它不是 nil。
  • " 这个链接上的解释:我们应该在 Swift 的闭包中总是使用 [unowned self] 来区分弱和无主是错误的。"怎么回事?

标签: ios swift automatic-ref-counting


【解决方案1】:

[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)
}

【讨论】:

  • 谢谢。这不是我的全部代码,我只是复制了有趣的部分。你说的有道理,但为什么它对 Objc 有效?
  • @Wak 我更新了我的答案,但是弱在 Objective-C 中默默地工作,因为你可以在 Objective-C 中向nil 发送消息
  • @Wak,我不能确定可能有什么不同。这可能只是一个竞争条件。但是,我对weak 的描述v.s. unowned / unsafe unretainedstrong 100% 准确。重要的是在 Swift 中删除 [weak self] in 是否可以解决您的崩溃问题。
  • ObjC 中没有unowned,所以当你说它在那里工作时,不清楚你的意思。 weak 也不应该崩溃; strong也不应该。
  • @RobNapier 在objective-c 中,unowned 被称为“unsafe unretained”。它确实存在,但名称不同
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-07
  • 1970-01-01
  • 2012-07-27
  • 1970-01-01
  • 1970-01-01
  • 2012-07-03
相关资源
最近更新 更多