gpt4 book ai didi

ios - 在 Apple 方法中隐式解包可选

转载 作者:可可西里 更新时间:2023-11-01 01:06:44 26 4
gpt4 key购买 nike

我正在尝试从 Objective-C 切换到 Swift。我不明白声明函数以返回 AnyObject! 而不是 AnyObject? 的意义。

例如:

func instantiateViewControllerWithIdentifier(identifier: String) -> AnyObject!

为什么这个方法返回一个隐式展开的可选而不是一个简单的可选?我得到了 AnyObject 部分,但是允许我们避免使用 ! 解包可选的(如果它可能为 nil)有什么意义呢? (因此使应用程序崩溃,即使这种情况极不可能发生)

我错过了什么?

这只是一种使用此方法的返回值而无需使用 ! 的便捷方式,还是有其他我看不到的东西?在这种情况下,如果程序返回 nil 就注定要崩溃吗?

我觉得:

  • AnyObject 意味着 100% 的机会返回一些东西
  • AnyObject? 表示有 50% 的机会返回 nil,您应该始终检查 nil
  • AnyObject! 意味着 99% 的机会返回非 nil 的东西,不需要检查 nil

此外,我假设与 Objective-C/NSObject 类有某种联系,但无法弄清楚是什么......

谢谢

最佳答案

Cocoa API 中隐式解包选项 (IUO) 的频率是将这些 API 从 ObjC 导入 Swift 的产物。

在 ObjC 中,所有对对象的引用都只是内存指针。就语言/编译器所知,任何指针在技术上总是可能为零。在实践中,一个接受对象参数的方法可能被实现为永远不允许传递 nil,或者一个返回对象的方法永远不会返回 nil。但是 ObjC 没有提供在 API 的 header 声明中断言这一点的方法,因此编译器必须假定 nil 指针对任何对象引用都是有效的。

在 Swift 中,对象引用不仅仅是指向内存的指针;相反,它们是一种语言结构。通过允许我们断言给定的引用总是指向一个对象,或者使用可选值来允许这种可能性并要求考虑到它,这会获得额外的安全性。

但是在引用很可能永远不会为 nil 的情况下,处理可选的展开可能会很痛苦。所以我们还有 IUO 类型,它允许您使用可选值而不用检查它们是否为 nil(风险自负)。

因为编译器不知道 ObjC API 中的哪些引用可以或不可以安全地为空,所以它必须使用某种可选类型导入 ObjC API(Apple 的或您自己的)中的所有对象引用。无论出于何种原因,Apple 选择对所有导入的 API 使用 IUO。可能是因为许多(但重要的是不是全部!)导入的 API 实际上是不可空的,或者可能是因为它允许您像在 ObjC 中一样编写链接代码(self.view.scene.rootNode 等)。

在某些 API(包括大部分 Foundation 和 UIKit)中,Apple 已手动审核导入的声明以使用完整的可选(例如 UIView?)或非可选引用(UIView) 在语义适当时代替 IUO。但并非所有 API 都经过审核,有些 API 仍在使用 IUO,因为这仍然是这些 API 最适合做的事情。 (例如,他们非常一致地总是将 id 导入为 AnyObject!。)

因此,回到您问题中的表格:最好不要从概率的角度思考。在处理返回的 API 时...

  • AnyObject:总是有一个值,不能为零。
  • AnyObject?:可能为 nil,必须检查是否为 nil
  • AnyObject!:没有保证。阅读该 API 的 header 、文档或源代码(如果可用),以了解它是否真的适合您的情况并相应地处理它。或者只是假设它可以为零并进行防御性编码。

instantiateViewControllerWithIdentifier的情况下, 有两个选项你可能认为同样有效:

  1. 假设您保证永远不会得到 nil,因为您知道您在 Storyboard中放置了一个带有该标识符的 View Controller 并且您知道它是什么类。

    let vc = storyboard.instantiateViewControllerWithIdentifier("vc") as MyViewController
    // do stuff with vc
  2. 假设您的 Storyboard将来可能会发生变化,并为自己设置一个有意义的调试错误,以防万一您破坏了某些东西。

    if let vc = storyboard.instantiateViewControllerWithIdentifier("vc") as? MyViewController {
    // do something with vc
    } else {
    fatalError("missing expected storyboard content")
    }

关于ios - 在 Apple 方法中隐式解包可选,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26019929/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com