为什么要创建“隐式解包选项”,因为这意味着您知道有一个值?

2023-12-31

为什么要创建“隐式解包可选”而不是仅创建常规变量或常量? 如果您知道它可以成功解包,那么为什么首先要创建一个可选呢? 例如,这是为什么:

let someString: String! = "this is the string"

将比以下更有用:

let someString: String = "this is the string"

如果“可选值表明允许常量或变量具有‘无值’”,但是“有时从程序的结构中可以清楚地看出,在首次设置该值之后,可选值将始终具有值”,那么有什么意义呢?首先让它成为可选的? 如果你知道一个可选值总是有一个值,那么这是否就意味着它不是可选的?


在我描述隐式解包选项的用例之前,您应该已经了解 Swift 中的选项和隐式解包选项是什么。如果你不这样做,我建议你先阅读我关于选项的文章 http://www.drewag.me/posts/what-is-an-optional-in-swift

何时使用隐式解包可选

创建隐式解包可选有两个主要原因。所有这些都与定义一个永远不会被访问的变量有关nil因为否则,Swift 编译器将始终强制您显式解开一个Optional。

1. 初始化时无法定义的常量

在初始化完成时,每个成员常量都必须有一个值。有时,常量在初始化时无法用正确的值进行初始化,但仍然可以保证在访问之前它有一个值。

使用可选变量可以解决此问题,因为可选变量会自动初始化为nil并且它最终包含的值仍然是不可变的。然而,不断地解开一个你确信不为零的变量可能会很痛苦。隐式解包的Options 实现了与Optional 相同的好处,但额外的好处是不必在任何地方显式地解包它。

一个很好的例子是,在加载视图之前,无法在 UIView 子类中初始化成员变量:

class MyView: UIView {
    @IBOutlet var button: UIButton!
    var buttonOriginalWidth: CGFloat!

    override func awakeFromNib() {
        self.buttonOriginalWidth = self.button.frame.size.width
    }
}

在这里,在视图加载之前您无法计算按钮的原始宽度,但您知道awakeFromNib将在视图上的任何其他方法(初始化除外)之前调用。您可以将其声明为隐式解包可选,而不是强制在整个类中毫无意义地显式解包该值。

2. 当你的应用程序无法从变量中恢复时nil

这应该是极其罕见的,但是如果你的应用程序无法继续运行,如果变量是nil当访问时,费心测试它是浪费时间nil。通常,如果您的应用程序必须满足一个条件才能继续运行,那么您将使用assert。隐式解包可选有一个内置的 nil 断言。即使如此,如果它为 nil,最好解开可选值并使用更具描述性的断言。

何时不使用隐式解包可选

1. 延迟计算成员变量

有时你有一个不应该为 nil 的成员变量,但在初始化期间无法将其设置为正确的值。一种解决方案是使用隐式解包可选,但更好的方法是使用惰性变量:

class FileSystemItem {
}

class Directory : FileSystemItem {
    lazy var contents : [FileSystemItem] = {
        var loadedContents = [FileSystemItem]()
        // load contents and append to loadedContents
        return loadedContents
    }()
}

现在,成员变量contents直到第一次访问时才初始化。这使类有机会在计算初始值之前进入正确的状态。

Note:这似乎与上面的#1 相矛盾。然而,有一个重要的区别需要做出。这buttonOriginalWidth上述必须在 viewDidLoad 期间设置,以防止任何人在访问该属性之前更改按钮宽度。

2. 其他地方

在大多数情况下,应该避免隐式解包选项,因为如果使用错误,整个应用程序将在访问时崩溃nil。如果您不确定变量是否可以为零,请始终默认使用普通的Optional。解开一个永远不会存在的变量nil当然不会很痛。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么要创建“隐式解包选项”,因为这意味着您知道有一个值? 的相关文章

  • SwiftUI 导航:如何将详细信息视图切换到不同的项目?

    我正在努力实现以下导航行为 用户可以从列表中选择一个项目 该项目会触发该项目的详细信息视图 在此详细视图上 导航栏中有一个 添加 按钮 可打开用于添加其他项目的模式表 到目前为止 一切都按预期进行 但添加项目后 我希望详细视图显示新项目 我
  • 重新定位时 Mapbox 默认的 compassView 会给出奇怪的结果

    我遇到一种情况 必须将地图框罗盘视图重新定位到不同的位置 当我以其他点作为其 compassView 轴旋转地图时 compassView 现在正在旋转 并给了我一个奇怪的结果 附截图 黑色mapBox默认罗盘图标是旋转的 参考截图 这是
  • 排除 Realm 模型类

    我的应用程序中配置了两个领域文件 我想存储我的Log将模型与其他模型分开保存为单独的文件 我的问题是我也看到了我的Log我不想要的默认 Realm 文件中的模型类 如何从给定的 Realm 文件中排除特定的模型类 我使用主 Realm 文件
  • 运行时警告 CLSUserDefaults 实施了两次

    在 cocoapod 源中使用 import 语法时 我在 pod 定义的类中看到了与下面类似的警告 但这是一个内部苹果类定义 CLSUserDefaults 我无法控制它 也不会进行子类化 我不知道这是否真的造成了问题 但它不应该发生 o
  • 以编程方式进行排序时检索 ViewController 堆栈

    static func showMenuView parentVC UIViewController let storyboard UIStoryboard name Main bundle nil let resultController
  • 快速从 appDelegate 中 popToRootViewController

    我试图从应用程序委托弹出到导航堆栈的根视图控制器 并且在将 obj c 中的内容转换为 swift 时遇到一些问题 obj c 中的工作原理 UINavigationController navigationController UINav
  • 如何获取多点触摸 UITapGestureRecognizer 的多个位置

    我的视图中有一个 UITapGestureRecognizer 我可以使用下面的代码很好地获取其触摸的位置 现在 如果我将此识别器的触摸次数更改为 2 或更多 它仍然会为我提供一个位置 如何获得两次触摸的两个位置 tapGesture lo
  • Swift 中 UIViewController 子类成员的双重初始化

    我想制作一个自定义容器视图控制器并向其子类添加一些成员UIViewController 当我尝试使用以下代码从应用程序委托初始化它时 self window UIWindow frame UIScreen mainScreen bounds
  • “无法调用非函数类型‘HTTPURLResponse’的值?”(Alamofire 4.0) [Swift 3.0]

    我收到此错误 无法调用非函数类型 HTTPURLResponse 的值 关于该部分 response request response data error 我想知道是否有人可以帮助我解决这个问题 Alamofire download ur
  • 根据图像制作具有 UIImageView 高度的 UICollectionViewCells

    我想做一个UICollectionView单元格的宽度是屏幕的宽度 但高度取决于单元格的宽高比UIImageView inside 在我目前的实施中 所有UICollectionViewCell实例是正方形 这不是我想要的 我想以某种方式使
  • CNContact 添加新的联系人问题

    我在通过以下方式添加联系人时遇到问题联系框架 我使用的是装有 iOS 12 1 2 的 iPhone 5s 设备 我添加联系人的代码如下 let saveRequest CNSaveRequest saveRequest add self
  • macOS 应用程序中还需要 Swift 的嵌入式 dylib吗?

    Swift 5 发行说明说 对于运行 iOS 12 2 watchOS 5 2 和 tvOS 12 2 的设备 Swift 应用程序不再在构建变体中包含 Swift 标准库和 Swift SDK 覆盖的动态链接库 但在同一上下文中没有提及
  • Swift 3 '[UIApplicationLaunchOptionsKey:任意]?'无法转换为 '[String : NSString]'

    我有一个 TVOS 应用程序已从 Swift 2 转换为 Swift 3 但出现以下错误 我不确定如何让它安静下来 UIApplicationLaunchOptionsKey 任意 无法转换为 String NSString 它出现在这段代
  • 如何在 Swift 中使用 CGFloat?

    var posinonY Float Float y Float pipeDown size height Float verticalPipeGap pipeDown position CGPointMake 0 0 Float posi
  • 检查 Option 是否包含特定 Some 值的最佳方法?

    您不能执行以下操作 if option is some option 1 既然如果option is some false第二次比较会出错 做这样的事情的最好方法是什么 我现在正在做什么 if option is some if optio
  • Firebase 连接管理器应仅返回一个结果

    我正在关注位于以下位置的文档 https www firebase com docs ios guide offline capability html section connection state https www firebase
  • 在事件聚合器中混合枚举与事件类

    我最近尝试实现自己的简单事件聚合器 我从 MSDN 上的事件聚合器文章中获得了很多灵感 关于 MSDN 上的事件聚合器 我注意到一件事是事件实际上是它们自己的类 这根本不是一件坏事 然而 我只是觉得总是为每个小事件创建一个新的空类很尴尬 我
  • Swift 如何设计 UIWebView 在 Story Board 中自动调整全屏大小

    我在 StoryBoard 中设计了一个 320x500 的 UIWebView 但是当在 Iphone 6 Plus 模拟器中运行时 我想要这个 webview 全屏或随设备屏幕缩放 如何在故事板中制作它 我在 ViewDidLoad 中
  • 打印附加结构(swift 4)

    我有三个 textifled 用于将数据附加到结构中 如何打印我附加的内容 现在我收到一条错误消息 import UIKit class ViewController UIViewController IBOutlet var c UITe
  • Android:单一活动,多个视图

    我不是 Android 专业人士 尽管我开发了一个包含 50 多个活动的应用程序 这使得该应用程序非常庞大 经过8周的开发 现在出现了一些问题 导致应用程序难以维护和升级 我正在处理的主要问题是 我无法将对象引用传递给活动的构造函数 事实上

随机推荐

  • 与重复的组合

    我正在使用 Mathematica 7 和 Combinatorica 包函数 我可以从元素列表中获取特定数量的所有组合 其中顺序无关紧要并且没有重复 例如 in KSubsets a b c d 3 out a b c a b d a c
  • 如何检查仅当鼠标位于特定位置时才存在的元素

    如果您需要检查元素的悬停状态 可以按照描述完成here https stackoverflow com questions 17602611 inspect a hover element问题是如果移动鼠标就会失去状态 就我而言 它的 ja
  • 绑定Vuejs的两个组件

    如何完美地组织两个 vuejs 组件之间的数据和交互 例如 1 我有一个组件 item v for item in items a item name 2 和第二个 card v for item in items div content
  • 如何停靠弹出窗口?

    我有一个包含 3 个主要小部件的应用程序 我也有一个弹出窗口QDockWidget 我正在尝试获取QDockWidget停靠到底部小部件的右半部分 但正如您在下图中看到的 我可以停靠窗口的唯一位置是应用程序的边缘 我怎样才能做到这一点QDo
  • 闪亮的传单地图弹出窗口正在提取错误的数据

    由于某种原因 Shiny传单应用程序上分配给多边形的弹出窗口提取了应分配给多边形的错误信息 似乎多边形已放置在地图上 然后以不同的顺序分配多边形属性 任何想法将不胜感激 server lt function input output ses
  • Google Cloud Load Balancer - 子域重定向到存储桶中的特定文件夹

    目前我们有以下需求 每个用户都可以在 Google 存储桶下拥有自己的子域和文件夹 其中包含应通过此子域提供的内容 例如 domain user1 example com gt bucket example com user1 index
  • 如何将表中的某些列复制到另一个mysql

    我有两张桌子 例如 table 1 A B C D E F G H I J table 2 A C D E G H J K L M N O P 我必须将一些列从表 2 复制到表 1 我尝试的是 INSERT INTO table 1 C D
  • json_encode PHP 对象及其受保护的属性

    有什么方法可以设置 PHP 对象 以便当我尝试将它们转换为 JSON 时 它们所有受保护的属性都会显示出来 我读过其他答案建议我添加一个toJson 函数到对象 但这可能并不能真正帮助我很多 在大多数情况下 我有一个对象数组 并对数组本身执
  • 在 Windows 窗体上的窗口一侧添加按钮

    我想在 C 上的 Windows 窗体一侧添加按钮 在外面 当窗口移动时 按钮应该一起移动 例如 我看到两个选择 要么将按钮放在单独的表单中 然后通过编码将两个表单粘在一起Move有可能Resize events 或者更简单 制作表格透明的
  • 在新行中添加 max(value)+1,这会是一个问题吗?

    在 SQL Server 表中 我有以下两列 RowId 主键 数字 标识列和自动插入 MailId 非键 数字 非标识 非自动插入 邮件 ID 可以重复 如果是新的 MailId 我将检查 max MailId 1 并将其插入新行中 如果
  • 如何在gridview中间歇性地展示横幅广告

    I am developing an android app that will have a screen similar to the following image 请注意单元格之间的横幅广告 由于 GridView 不支持这种跨列
  • 为什么在 epoll 中推荐使用非阻塞套接字

    我正在尝试学习如何将 epoll 用于 tcp 服务器应用程序 因为我期望有很多连接 我尝试检查示例和教程 他们总是建议使用 设置在 epoll 中添加的套接字为非阻塞套接字 为什么 对于级别触发的 epoll 非阻塞套接字可以帮助最大限度
  • C# Groupby 然后在分割 CSV 后求和(无标题)

    阅读了各种帖子后 我认为我已经接近得到我想要的结果 但 总和 部分给出了错误的答案 我怀疑这是由于我调用 总和 的方式造成的 因为我的 csv 文件没有列标题 csv 文件包含以下内容 222 1 223 2 222 1 224 2 222
  • 偏移GPS坐标的公式/算法

    我以纬度 经度的形式提供 GPS 坐标 并希望将它们偏移距离和角度 例如 如果我偏移 新坐标是多少45 12345 7 34567沿方位 104 度行驶 22 公里 Thanks 对于大多数应用 这两个公式之一就足够了 给定径向和距离的纬度
  • 收到错误 /bin/sh: 1: 源: 未找到

    我正在尝试构建 docker 并安装 nvm 一些代码行 RUN curl https raw githubusercontent com creationix nvm v0 25 0 install sh bash RUN source
  • 使用 Visual Studio 扩展设置光标位置

    我正在编写自己的 Visual Studio 2010 扩展 它应该可以帮助我浏览一个相当大的解决方案 我已经有一个基于对话框的 VS 扩展 它根据某些搜索条件显示类名和函数名 我现在可以单击此类 方法 然后我就可以打开正确的文件并跳转到该
  • C# OpenGL字体显示

    我正在Windows中使用Tao框架开发2D CAD应用程序 我想使用 Windows 库中的字体来显示绘图信息 除此之外 我想旋转缩放我的文本 对于位图字体我无法做到这一点 我进行了 OpenGL 字体调查 http www opengl
  • SQL-合并两个具有不同日期值的表

    我正在开发一个在网站上显示股票信息的项目 我想问一下如何在SQL中合并两个表 假设我们有表1 stock id date p high p low 3 2013 02 26 100 80 3 2013 02 25 100 80 3 2013
  • 如何使用python获取一列数据中包含的特定行的时间差

    这里我有一个包含时间和三个输入的数据集 这里我用panda来计算时差 代码是 data Time different pd to timedelta data time astype str diff 1 dt total seconds
  • 为什么要创建“隐式解包选项”,因为这意味着您知道有一个值?

    为什么要创建 隐式解包可选 而不是仅创建常规变量或常量 如果您知道它可以成功解包 那么为什么首先要创建一个可选呢 例如 这是为什么 let someString String this is the string 将比以下更有用 let s