尝试在 Swift 中访问无主引用总是会导致应用程序崩溃

Posted

技术标签:

【中文标题】尝试在 Swift 中访问无主引用总是会导致应用程序崩溃【英文标题】:Trying to access an unowned reference in Swift always causes the app to crash 【发布时间】:2014-06-14 07:18:44 【问题描述】:

在 WWDC 2014 之前,我正在学习 Objective-C。我创建了一个“电梯模拟器”应用程序,它的存在只是为了我的学习目的。当您单击七个按钮中的一个时,它会关闭电梯门(动画),一次向所选级别移动一层(如文本标签和按钮颜色所示),然后重新打开门。

随着 WWDC 和 Swift 的发布,我正在尝试在 Swift 中重新创建这个应用程序。到目前为止,我发现 Swift 更好用,但我遇到了一个关于无主引用的主要障碍。该应用程序启动良好,直到我实现了文本标签和按钮颜色的功能,以在应用程序启动时根据 Elevator 模型的属性进行设置。实现这些功能后,应用总是在启动时崩溃。

最终,我将问题缩小到从视图控制器到 Elevator 模型的任何调用中。在注释掉对我的视图控制器方法的调用以更新界面后,应用程序再次正常启动,我可以通过尝试调用初始化程序来确认问题在于调用电梯模型。以下代码 sn-ps 重现了该问题:

应用代理:

var window: UIWindow?
let mainElevator = Elevator()

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool 
    window = UIWindow(frame: UIScreen.mainScreen().bounds)

    mainElevator.view = ViewController(elevator: mainElevator)
    window!.rootViewController = mainElevator.view

    window!.makeKeyAndVisible()
    return true

电梯(型号):

class Elevator: NSObject 

    var view: ViewController?
    var currentLevel = 1
    var newLevel: Int?

视图控制器:

class ViewController: UIViewController 

    unowned let elevator: Elevator

    init(elevator: Elevator) 
        self.elevator = elevator
        super.init(nibName: nil, bundle: nil)
        //self.elevator.currentLevel = 3
    

注意:我已经在这些类中发出了其他方法,因为它们似乎对问题没有影响。我通过使用 PersonCreditCard 示例(Apple 用作示例)创建了一个类似的场景来确认这一点,这些示例仅由我在上面粘贴的部分组成。

ViewController 的最后一行注释掉后,应用程序启动正常(显示基于 loadView()viewDidLoad() 的视图),但如果我取消注释,应用程序就会崩溃。如果我将引用类型更改为弱和可选,它也可以正常工作,但它不应该是弱的、可选的、 变量。电梯将永远存在(但不一定是视图,由于多任务处理),它应该是恒定的。这正是 Apple 在 Person/CreditCard 场景中描述的那种情况。

另外,如果我从最后一个齿中删除 self.(因此使用本地版本的 elevator),它可以正常工作。所以模型并没有被释放,只是无主引用不起作用。

编辑:崩溃报告

libswift_stdlib_core.dylib`_swift_abortRetainUnowned:
0x1001c3980:  pushq  %rbp
0x1001c3981:  movq   %rsp, %rbp
0x1001c3984:  leaq   0x176a7(%rip), %rax       ; "attempted to retain deallocated object"
0x1001c398b:  movq   %rax, 0x792ce(%rip)       ; gCRAnnotations + 8
0x1001c3992:  int3   
0x1001c3993:  nopw   %cs:(%rax,%rax)        Thread 1: EXC_BREAKPOINT (code=EXT_1386_BPT, subcode=0x0)

【问题讨论】:

您看到了什么样的崩溃消息(感谢目前 Xcode 6 的长镜头...) 我已更新问题以包含来自 Xcode 的报告。这是你要求的吗? 是的,我就是这个意思。 【参考方案1】:

我猜这是一个错误。

如果您的 Elevator 类没有从 NSObject 继承,它可以工作。否则你会收到很长的错误信息。

class Elevator 

    var view: ViewController?
    var currentLevel = 1
    var newLevel: Int?

【讨论】:

嗯,这很有趣。是的,它解决了问题。我记得苹果说过“你不需要继承 NSObject,但你可以”。我猜这样做的原因是在 Objective-C 特定函数中使用该类?我只是想知道子类化是否更好。 @JamesFletcher 有人已经在 SO 中问过这个问题:***.com/questions/24057525/…

以上是关于尝试在 Swift 中访问无主引用总是会导致应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章

Swift学习笔记-自动引用计数弱引用和无主引用

快速无主的安全

取消引用已删除的指针总是会导致访问冲突?

在 Swift 3(核心数据)中引用实体属性

迅速。无主的(绝对)唯一的特定优势是弱性能吗?

_swift_abortRetainUnowned 将 @objc 类捕获为无主时