所以我知道’!’之间的区别和’?’,我只想知道在调用可选变量的方法时使用它们的最佳方法是什么
var bar: Bar? = nil bar?.doSomething() // this will be valid,but wouldn't call doSomething bar!.doSomething() // Given error: EXC_BAD_INSTRUCTIONS (ObvIoUsly)
bar = Bar() bar?.doSomething() // Valid bar!.doSomething() // Valid
所以我的问题是,什么是调用可选变量的方法的最佳方式,我个人使用:
if bar != nil { bar!.doSomething() }
或者将bar?.doSomething()做的完全一样?
我认为这是不正确的建议,以避免bar?.doSomething(),并始终使用如果让bar = bar {…}代替.
主要有两个原因:
首先,bar?.doSomething()只是简明扼要.如果您正在使用条件表达式中的一个语句编写一个let,那么您应该问自己是否不希望将该代码放在一个较短版本的单行上.
虽然这是完全合法的代码
if let thing = thing { thing.bar() }
..以下是合法的,只是短了很多..
thing?.bar()
第二,更重要的是这个问题的核心,它们是不一样的!如果let是一个组合测试,可选的解包和赋值吧?做一个叫做可选链接的东西.
后者在许多情况下非常有用,可以让您编写更好的代码.例如:
它可以用来代替这个..
var imageGenerator: ImageGenerator? if let generator = imageGenerator { myView.image = generator.generateImage() } else { myView.image = nil }
简单地说:
myView.image = self.imageGenerator?.generateImage()
原因是因为可选链接在链中遇到零时返回零.因为UIImageView有一个图像:UIImage?,它需要这个零值.即使它来自ImageGenerator?
当与无合并运算符组合时,它更有用.
现在你可以转这个代码..
var imageGenerator: ImageGenerator? if let generator = imageGenerator { myView.image = generator.generateImage() } else { myView.image = DefaultImage }
..进..
myView.image = generator?.makeImageGenerator() ?? DefaultImage
这是更简洁的方式.
并且因为可选链在链上工作..你甚至可以做一些像:
myView.image = delegate?.makeImageGenerator()?.generateImage() ?? DefaultImage
哪个会变成..
if let delegate = delegate { if let generator = delegate.generatorForImage() { if let image = generator.generateImage() { myView.image = image } else { myView.image = DefaultImage } } else { myView.image = DefaultImage } } else { myView.image = DefaultImage }
..如果您没有使用可选链接和无合并运算符.
(是的,myView.image = DefaultImage只能在有条件地完成,但这意味着你仍然必须引入额外的代码来检查它是否被设置,它不会更短.)
那里有两个新的技巧:-)