本文转载自:代码手工艺人的博客,原文名称:Swift之 ? 和 !
Swift语言使用var定义变量,但和别的语言不同,Swift里不会自动给变量赋初始值,也就是说变量不会有默认值,所以要求使用变量之前必须要对其初始化。如果在使用变量之前不进行初始化就会报错:
var stringValue : String //error: variable 'stringValue' used before being initialized //let hashValue = stringValue.hashValue // ^ let hashValue = stringValue.hashValue
上面了解到的是普通值,接下来Optional值要上场了。经喵神提醒,Optional其实是个enum
,里面有None
和Some
两种类型。其实所谓的nil就是Optional.None
, 非nil就是Optional.Some
, 然后会通过Some(T)
包装(wrap)原始值,这也是为什么在使用Optional的时候要拆包(从enum里取出来原始值)的原因, 也是PlayGround会把Optional值显示为类似{Some "hello world"}
的原因,这里是enum Optional的定义:
enum Optional<T> : LogicValue, Reflectable { case None case Some(T) init() init(_ some: T) /// Allow use in a Boolean context. func getLogicValue() -> Bool /// Haskell's fmap, which was mis-named func map<U>(f: (T) -> U) -> U? func getMirror() -> Mirror }
声明为Optional只需要在类型后面紧跟一个?
即可。如:
var strValue: String? //?相当于下面这种写法的语法糖 var strValue: Optional<String>
一旦声明为Optional的,如果不显式的赋值就会有个默认值nil。判断一个Optional的值是否有值,可以用if来判断:
if strValue { //do sth with strValue }
然后怎么使用Optional值呢?文档中也有提到说,在使用Optional值的时候需要在具体的操作,比如调用方法、属性、下标索引等前面需要加上一个?
,经喵神指正,”Optional Chaining的问号的意思是询问是否响应后面这个方法,和原来的isResponseToSelector
有些类似”,如果是nil值,也就是Optional.None
,固然不能响应后面的方法,所以就会跳过,如果有值,就是Optional.Some
,可能就会拆包(unwrap),然后对拆包后的值执行后面的操作,比如:
let hashValue = strValue?.hashValue
strValue是Optional的字符串,如果strValue是nil,则hashValue也为nil,如果strValue不为nil,hashValue就是strValue字符串的哈希值
到这里我们看到了
?
的两种使用场景:
1.声明Optional值变量
2.用在对Optional值操作中,用来判断是否能响应后面的操作
另外,对于Optional值,不能直接进行操作,否则会报错:
//error: 'String?' does not have a member named 'hashValue' //let hashValue = strValue.hashValue // ^ ~~~~~~~~~ let hashValue = strValue.hashValue
上面提到Optional值需要拆包(unwrap)后才能得到原来值,然后才能对其操作,那怎么来拆包呢?拆包提到了几种方法,一种是Optional Binding
, 比如:
if let str = strValue { let hashValue = str.hashValue }
还有一种是在具体的操作前添加!
符号,好吧,这又是什么诡异的语法?!
直接上例子,strValue是Optional的String:
let hashValue = strValue!.hashValue
这里的!
表示“我确定这里的的strValue一定是非nil的,尽情调用吧” ,比如这种情况:
if strValue { let hashValue = strValue!.hashValue }
{}里的strValue一定是非nil的,所以就能直接加上!,强制拆包(unwrap)并执行后面的操作。 当然如果不加判断,strValue不小心为nil的话,就会出错,crash掉。
考虑下这一种情况,我们有一个自定义的MyViewController
类,类中有一个属性是myLabel
,myLabel是在viewDidLoad中进行初始化。因为是在viewDidLoad中初始化,所以不能直接声明为普通值:var myLabel : UILabel
,因为非Optional的变量必须在声明时或者构造器中进行初始化,但我们是想在viewDidLoad中初始化,所以就只能声明为Optional:var myLabel: UILabel?
, 虽然我们确定在viewDidLoad中会初始化,并且在ViewController的生命周期内不会置为nil,但是在对myLabel操作时,每次依然要加上!
来强制拆包(在读取值的时候,也可以用?
,谢谢iPresent在回复中提醒),比如:
myLabel!.text = "text" myLabel!.frame = CGRectMake(0, 0, 10, 10) ...
对于这种类型的值,我们可以直接这么声明:var myLabel: UILabel!
, 果然是高(hao)大(gui)上(yi)的语法!, 这种是特殊的Optional,称为Implicitly Unwrapped Optionals
, 直译就是隐式拆包的Optional,就等于说你每次对这种类型的值操作时,都会自动在操作前补上一个!
进行拆包,然后在执行后面的操作,当然如果该值是nil,也一样会报错crash掉。
var myLabel: UILabel! //!相当于下面这种写法的语法糖 var myLabel: ImplicitlyUnwrappedOptional<UILabel>
那么
!
大概也有两种使用场景
1.强制对Optional值进行拆包(unwrap)
2.声明Implicitly Unwrapped Optionals
值,一般用于类中的属性
Swift是门新生的语言,我们有幸见证了它的诞生,激动之余也在佩服苹果大刀阔斧的推出一个新的语言替代一个已经比较成熟语言的魄力,今天在知乎 日报上看到一个回答是说Swift是一门玩具语言,正当想去吐槽,发现回答已经被删除了。个人认为苹果是很认真的推出Swift的,从Swift的各种细 微的设计也能看的出来。
另外这两个小符号就花费了我不少的时间来理解,可能依然会有错误和不妥之处,欢迎大家指正,本文旨在抛砖引玉。除此之外,Swift还有很多很棒的特性,WWDC 2014 会有四五个和Swift语言相关的Video,大家也可以去关注一下。
最后要感谢喵神的纠正了多处有问题的地方,thx, have fun!
主要参考自苹果的官方文档《The Swift Programming Language》,可以在这里下载到
相关推荐
关于新语言swift的?和!知识点 欢迎学习 独家分享
主要给大家介绍了关于swift中可选值?和!使用的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
主要介绍了Swift中 !和 ?的区别及使用的相关资料,需要的朋友可以参考下
在Swift 4.2中是否有用于为按钮和其他控件提供阴影效果的吊舱? 请帮我! 我才很快就花了两个星期,为此花了两个星期! 有人请帮助我! 我尝试过的内容:我尝试过Material design MDKit! 但不适用于...
azure-functions-swift:Swift中的Azure函数! 纯粹在Swift中!
SwiftDispatchAfter SwiftDispatchAfter 是在 Swift 中调用dispatch_after小代码片段。 这个想法属于 Matt Neuburg ( )。 添加了一些covinience方法。 #用法添加use_frameworks! 到你的 Podfile 添加pod '...
声明ImplicitlyUnwrappedOptionals值,一般用于类中的属性
Swish:?构建在一台远程机器Xcode中的Swift项目
Swift 中的闭包和 Objective-C 中的Block讲解
石英渲染器曾经想将 Quartz 合成渲染成一系列帧吗? 现在你可以!
? Swift do-try-catch的语法糖衣
swift 报文中文手册 第一章 SWIFT 基础知识 第二章 SWIFT MX1XX 客户汇款及...第四章 SWIFT MT3XX 外汇买卖和存放款 第五章 SWIFT MT4XX 托收 第六章 SWIFT MT7XX 信用证 第七章 SWIFT MT9XX 资金管理与客户帐户状况
Swift中的Down Blazing快速Markdown(CommonMark)渲染,基于cmark v0.29.0构建。 您的应用程序正在使用它吗? 让我们知道! 维护者Rob Phillips John Nguyen Keaton Burleson用cmark v0.29.0构建了Swift中的快速...
Kotlin Multiplatform 示例深受Wordle游戏以及Word Master和wordle-solver示例的启发。主要游戏逻辑/状态包含在具有基本 UI 的共享 KMP 代码中,然后包含在以下客户端中 iOS (SwiftUI) Android(Jetpack 组合) ...
2022年2月26日,美国和欧盟、英国及加拿大发表联合声明,宣布禁止俄罗斯的几家主要银行使用SWIFT。 3月2日,欧盟发布公报,将主要的7家俄罗斯银行排除在SWIFT系统之外。 这个制裁手段号称“金融核弹”。 SWIFT到底是...
Swift 是一种新的编程语言,用于编写 iOS 和 OS X 应用。Swift 结合了 C 和 Objective-C 的优点并且不受 C 兼容性的限制。 Swift 采用安全的编程模式并添加了很多新特性,这将使编程更简单,更灵活,也更有趣。Swift...
它支持代码预览(playgrounds),这个革命性的特性可以允许程序员在不编译和运行应用程序的前提下运行 Swift 代码并实时查看结果。 Swift 通过采用现代编程模式来避免大量常见编程错误: * 变量始终在使用前初始化。...
Swift进阶 Swift4Swift进阶 Swift4Swift进阶 Swift4Swift进阶 Swift4Swift进阶 Swift4Swift进阶 Swift4Swift进阶 Swift4Swift进阶 Swift4Swift进阶 Swift4Swift进阶 Swift4Swift进阶 Swift4Swift进阶 Swift4Swift...