Swift Optionals:你应该什么时候期待它们

时间:2017-10-31 16:52:18

标签: swift optional

所以我正在教自己Swift,当我宣布它们时我得到了选项,例如:

var thisString:String?

我必须强行解开thisString,或者使用

if let anotherString = thisString {

或使用

guard if let another string = thisString else { return }

或nil合并

let anotherString = thisString ?? "Something else"

但是我被挂断的地方有时会创建一些我不认为是可选的但是编译器会做的事情。

例如,为什么URL在这里是可选的?

let myURL = URL(string: "https://itunes.apple.com/search?term=U2")
var myRequest = URLRequest(url: myURL!)

我没有声明它是一个可选的,它显然有一个值。那么为什么编译器会将此视为可选项?如果我没有强行打开它,我会收到这个错误:

Value of optional type 'URL?' not unwrapped; did you mean to use '!' or '?'?

我缺少一些标准吗?我已经阅读了Big Nerd的文档和Swift编程手册,我似乎仍然没有得到这一部分。

谢谢你的帮助。

5 个答案:

答案 0 :(得分:4)

  

但是我被挂断的地方有时会创建一些我不认为是可选的但编译器可以做的事情。

但你认为不重要的是什么。重要的是您调用的API实际返回的内容。你可以通过阅读文档找到答案。

  

那么为什么编译器会将此视为可选

好吧,让我们阅读文档。您正在呼叫URL(string:)。这与网址init(string:)相同。看看文档:

https://developer.apple.com/documentation/foundation/url/1779737-init

宣言是

init?(string: String)

看问号?这意味着,“此调用返回一个Optional。”所以你应该期待一个可选的。

答案 1 :(得分:2)

编译器无法确定您在字符串中定义的URL是否有效。

假设而不是:

let myURL = URL(string: "https://itunes.apple.com/search?term=U2")

您错过了将myURL定义输入为:

let myURL = URL(string: "https:/itunes.apple.com/search?term=U2")

该字符串包含格式错误的URL,因此程序会在您定义myURL时崩溃。

答案 2 :(得分:0)

 let myURL = URL(string: "https://itunes.apple.com/search?term=U2")

这里你是从string创建一个url。这个字符串可能不是一个有效的字符串。所有的字符串都不是有效的URL。所以你得到一个可选的,因为如果该字符串可以打开到一个有效的URL然后将返回该URL,否则将返回nil。请参阅Apple documentation here.您使用的初始化程序本身就是一个可用的初始化程序。

  init?(string: String)

答案 3 :(得分:0)

@Keshav是正确的,为了更好的想法,按住选项按钮并单击URL类的init函数的'string'部分。您将在swift引用中看到init声明为init?(string: String)。这意味着返回一个可选项。任何函数都可以返回一个可选项,您可以func returnMyString(_ myString: String) -> String {}func returnMyString(_ myString: String) -> String? {}。这两个函数几乎完全相同,除了第二个函数返回一个可选项。

答案 4 :(得分:0)

URL有可选的初始值设定项。例如,您可以拥有

class A {

    init?() {
        return nil //You will get Optional<A>.none
    }

}

A() === Optional<A>.none //true

哪种意味着初始化失败。这样的初始化器将返回的对象包装成Optional。在Swift nil == Optional<Any>.none中,您可以互换地谈论它们。

例如,如果您尝试使用不是实际网址的内容构建URL,则返回nil。

let notAURL = URL(string: "{") //notAURL will be nil 

侧面说明:我认为可选的初始化程序是一个非常糟糕的设计选择,因为它们无法就init内部出错的方式进行任何沟通。如果init是错误的,它应该throw。我不明白为什么Swift设计师允许使用可选的初始化器,我明白为什么它会产生很多混乱。