草庐IT

swift - 为什么要创建 "Implicitly Unwrapped Optionals",因为这意味着您知道有一个值?

coder 2023-07-14 原文

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

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

将比:

更有用
let someString: String = "this is the string"

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

最佳答案

在我描述隐式展开可选项的用例之前,您应该已经了解什么是 Swift 中的可选项和隐式展开可选项。如果你不这样做,我建议你先阅读 my article on optionals

何时使用隐式解包可选

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

1。无法在初始化期间定义的常量

每个成员常量在初始化完成时必须有一个值。有时,一个常量在初始化时不能被初始化为正确的值,但仍然可以保证它在被访问之前是有值的。

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

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

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

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

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

2。当您的应用无法从变量为 nil

时恢复

这应该是非常罕见的,但是如果你的应用程序在访问时变量为 nil 时无法继续运行,那么为 nil<>。通常,如果您有一个条件必须绝对成立才能让您的应用程序继续运行,您可以使用 assert。一个隐式解包的 Optional 有一个内置的 nil 断言。即便如此,如果它为 nil,通常最好解开可选值并使用更具描述性的断言。

何时不使用隐式解包可选

1。延迟计算的成员变量

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

class FileSystemItem {
}

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

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

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

2。其他地方

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

关于swift - 为什么要创建 "Implicitly Unwrapped Optionals",因为这意味着您知道有一个值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24006975/

有关swift - 为什么要创建 "Implicitly Unwrapped Optionals",因为这意味着您知道有一个值?的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby - 如何在 Ruby 中顺序创建 PI - 2

    出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits

  3. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  4. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

  5. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  6. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  7. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  8. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  9. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  10. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

随机推荐