英语PDF下载链接http://download.csdn.net/detail/tsingheng/7480427
Swift是用来开发iOS和OS X应用的新语言,可是很多地方用起来跟C或者OC是差点儿相同的。
Swift提供了C语言和OC的基本数据类型,比方整型用Int,浮点型用Double或者Float,布尔型用Bool,字符串文本用String。Swift还提供了两种集合类型。Array和Dictionary,后面会介绍。
Swift也跟C一样用唯一的变量名来存储与使用数据,还能使用一些值不会变的变量,应该说是常量,比C里面的常量要强大。在涉及到一些值不会发生变化的数据时使用常量类型能让代码更安全整洁。
除了跟C和OC相似的类型之外,Swift还添加了一些OC中没有的类型。比方元组,使用元组能够创建或者传递多个值。函数返回值使用元组就能够返回多个值了。
Swift还添加了可选类型。
可选类型的变量要么有个确切值,要么是没有值。
有点儿像OC里面值为nil的指针。可是OC里面指针仅仅能用于对象,Swift可选类型能用于不论什么数据类型。
可选类型比OC中的nil指针更安全更好用,Swift非常多核心牛逼的特性都要指望他。
可选类型也能说明了Swift是一种类型安全的语言。Swift能让程序猿清楚知道自己使用的是什么类型。
假设代码中须要一个String对象,类型安全机制能够保证Int之类的非String类型对象被传过来。
类型安全机制能让你在写代码的时候就能发现并纠正一些错误。
1.常量和变量
常量跟变量都由名称跟值组成,常量的值一旦设置就不同意再改变。变量就没有这个限制了。仅仅要类型没错就能为所欲为。
常量和变量的声明
常量和变量在使用之前都必须声明。常量用let声明,变量用var声明。这边有个样例用常量和变量来记录用户尝试登录次数。
let maximumNumberOfLoginAttempts = 10
var currentLoginAttempt = 0
这两行代码能够这样翻译:“声明一个叫做maximumNumberOfLoginAttempts的常量,给他赋值为10,然后声明一个叫currentLoginAttempt的变量,给他赋值为0。”
这个样例里面maximumNumberOfLoginAttempts是被声明为常量的,由于最多同意登录尝试次数是固定的。不会变的。
而currentLoginAttempt表示用户当前已经尝试的次数。是随着用户登录尝试要添加的,所以要被定义成变量。
声明变量或者常量的时候也能够一行声明多个。中间用逗号分隔。
比方 var x = 0.0, y = 0.0, z = 0.0
NOTE 假设代码里面要用到不会改变的值。尽量都用let声明成常量,仅仅有须要改变的才声明成变量。
类型标注
声明变量或者常量的时候还能够加个类型标注,来限定这个变量或者常量能够存储什么类型的值。写法是在变量名或常量名后面加上冒号空格再加存储类型。举个样例。我要声明一个存储String类型的变量,代码就是 var welcomeMessage: String。冒号的意思是“...类型为...”。所曾经面的代码能够翻译成:“声明一个类型为String的变量welcomeMessage”。“类型为String”意思是说“能够存储不论什么的String值”。
welcomeMessage如今能够被赋值,不会报错了。 welcomeMessage = “Hello”
NOTE 实际上这个类型标注可能非常少用,假设在声明变量或者常量的时候就给他个初始值,编译器就能自己判断出来变量或者常量的类型是什么了。这个在后面类型安全与类型判断里面会江到。上面这个样例中welcomeMessage没有初始值。所以编译器没有办法判断出来他是什么类型,也就须要用类型标注来指明变量类型了。
变量或常量命名
Swift变量常量命名非常自由,甚至能够用中文或者表情字符来命名。
let π = 3.14159
let 你好 = "你好中国"
let 狗狗表情 = "dogcow"
可是名称里面不能包括数学符号,大于小于号。或者保留的(或者非法的)Unicode编码位。或者连接线与制表符。也不能用数字打头。可是后面能够用数字。
变量或者常量的名字不能反复声明,类型也不能变。变量跟常量也不能互相转变。
NOTE 假设你想用Swiftkeyword同名的名字,你能够在名字前后加上倒引號(好像是数字1前面那个键)即可了。只是要尽量避免使用keyword。除非说是没的选了(比方说领导要求的)。
变量的值能够改成跟现有值同样类型的值。
var friendlyWelcome = "Hello!"
friendlyWelcome = "Bonjour!"
// friendlyWelcome is now "Bonjour!"
常量就不一样了,常量值一旦设定就不能改了,假设要给常量再赋值,就会报错了。
let languageName = "Swift"
languageName = "Swift++"
// this is a compile-time error - languageName cannot be changed
输出常量和变量
能够使用println函数来输出常量或者变量的值。
println(frientlyWelcome)
//输出“Bonjour”
println是用来输出的全局函数。输出结果最后会自己主动换行。
假设是用Xcode,println函数会把结果输出到Xcode的控制台。(还有另外一个函数print,也是用来输出的,可是print输出的结尾不会自己主动换行。)
println函数能够输出不论什么字符串。
println("This is a string")
// prints "This is a string"
println函数还能用来输出更复杂的日志。跟Cocoa的NSLog函数差点儿相同。
日志能够包括常量也能包括变量。
Swift使用字符串填补的方式在长字符串中使用常量或者变量。
用法是用括号把变量名括起来,前面在加个反斜杠。然后直接放入字符串中。
println("The current value of friendlyWelcome is \(friendlyWelcome)")
// prints "The current value of friendlyWelcome is Bonjour!"
NOTE 使用字符串填补时的其它全部选项在后面字符串填补里面会有介绍。
2.凝视
使用凝视能够在代码中增加一段不被运行的文字。编译器编译的时候会把全部的凝视都忽略掉。
Swift的凝视跟C的凝视很像,单行凝视用双斜杠打头。比方 // 这是一行凝视
多行凝视用/*开头,*/结尾
/* this is also a comment,
but written over multiple lines */
可是多行凝视有一个跟C不一样的地方,Swift的多行凝视能够嵌套。你能够先写一个/*开头。然后再写个/*作为内层凝视,然后先用*/表示内层凝视结尾。再写个*/表示外层凝视结尾。
/* this is the start of the first multiline comment
/* this is the second, nested multiline comment */
this is the end of the first multiline comment */
能够嵌套的多行凝视能让我们非常方便的凝视掉一大块儿内容,不用事先去看这块儿内容里面是不是已经有多行凝视了。
3.分号
跟很多编程语言不一样。Swift不要求在每一行语句后面加分号。只是你要是想加也能够加。可是假设要在一行写多条语句就必须加分号了。
let cat = "cat"; println(cat)
4.整型
整型数是指没有小数的数字。比方42啊,-23啊之类的。整型要么是有符号的(正数,0,负数)要么是无符号的(正数或者0)。
Swfit的无符号数提供8位。16位,32位以及64位的版本号。这些类型的命名方式跟C是差点儿相同的。
比方8位的无符号整型是UInt8,32位有符号整型是Int32。跟其它类型一样,这些类型首字母都要大写。
整型范围
你能够通过整型类型的min属性和max属性来获取各自的最小值和最大值。
let minValue = UInt8.min // minValue is equal to 0, and is of type UInt8
let maxValue = UInt8.max // maxValue is equal to 255, and is of type UInt8
使用上面两个属性得到的数值的类型跟使用的类型是一样的,比方上面得到的minValue和maxValue类型都是UInt8,假设要在表达式里面跟其它变量计算或者比較,那其它的变量类型也要是这个类型。
Int
大部分情况下你不须要去指定整型详细是几位的,Swift提供了第二种整型类型,Int,这个类型的长度跟程序执行的机器字长一样。32位平台执行,Int长度就跟Int32一样。64位平台执行,Int长度就跟Int64一样。
除非说你一定要使用特定长度的整型,不然尽量用Int来表示整型。这样能提高代码的一致性和通用性。就算是32位平台,Int存储范围是-2147483648到2147483647,这范围足够大了。
UInt
Swift还提供了一种没有符号的整型UInt,跟Int一样长度由程序执行的平台决定。
NOTE 仅仅有当你确实须要使用无符号数的时候採用UInt,不然尽量使用Int,就算你知道要保存的值不会有负数。使用Int能增强代码的一致性和通用性,避免了各种类型数字计算的时候再去类型转换。
5.浮点数
浮点数就是带小数部分的数字。比方3.1415。-273.354。
浮点型能存储的数字范围比整型大得多。而且能够存储比整型数最大值更大的数,和比整型数最小值更小的值。
Swift提供两种带符号的浮点数类型。
- Double:占用64位,当要存储的值很很大并且须要很精确的时候用Double。
- Float:占32位,当你要用小数可是用不着Double的时候就用Float。
NOTE Double类型提供至少15位小数的精度。Float的小数精度仅仅有6位。
选哪种类型要依据你要处理的数据的实际情况。
6.类型安全与类型判断
Swift是一种类型安全的语言。类型安全的语言要让你清楚自己使用的变量是什么类型。假设变量是String类型。就不能赋Int值给他哦。
由于Swift是类型安全的,所以编译器在编译代码的时候要进行类型检查,对于不论什么类型匹配不对的地方都会报错。这个特性能让你在开发的时候就发现并纠正非常多错误了。
当你要处理各种各样不同类型的数据的时候,类型检查能帮你避免非常多错误。
可是并非说你必须在声明每个常量或者变量的时候就要指定相应的类型。
假设你不指定。Swift会自己主动判断出相应的类型。类型判断能够让编译器在编译的时候通过你提供的值来自己主动判断出其所相应的数据类型。
由于有了类型判断,Swift里面的类型声明就比C或者OC这种语言里面少的多了。
当你声明常量或者变量的同一时候还提供初始值得时候类型判断就很好用了。通常要在声明变量或者常量的时候给他提供一个字面值。(字面值就好比是个马上数,不须要额外计算的。比方以下样例中的42或者3.14159。
)
比方假设你把字面值42赋给一个刚声明的常量,可是不指定常量类型,Swift会判断出来这个常量是Int类型的,由于你提供的初始值是Int类型的。
let meaningOfLife = 42
// meaningOfLife is inferred to be of type Int
假设你用浮点数做初始值。而且不指定类型,Swift判断出来的结果就是Double。
let pi = 3.14159
// pi is inferred to be of type Double
Swift判断小数类型的时候结果是Double而不会是Float。
假设你在表达式里用整数和小数相加,结果判断出来的是Double。
let anotherPi = 3 + 0.14159
// anotherPi is also inferred to be of type Double
字面值3没有明白表示自己的类型,而表达式中出现了Double类型。所以最后判断出来的类型是Double。
7.数字字面值
整数字面值能够用以下几种方式表示:
- 十进制数字。没有前缀
- 二进制数字,0b开头
- 八进制数字,0o开头
- 十六进制数字,0x开头
比方以下这几个数字的十进制值都是17
let decimalInteger = 17
let binaryInteger = 0b10001 // 17 in binary notation
let octalInteger = 0o21 // 17 in octal notation
let hexadecimalInteger = 0x11 // 17 in hexadecimal notation
小数字面值能够是十进制(没有前缀),护着十六进制(0x开头)。小数点两边都必须有数字。浮点数还有第二种指数表示方法,十进制浮点数用大写或小写字母E,十六进制浮点数用大写或小写字母P。
对于十进制来说假设指数是exp,就表示用基数乘以10的exp次方:
- 1.25e2表示1.25乘以10的2次方。或者125.0
- 1.25e-2表示1.25乘以10的-2次方,或者0.0125
对于十六进制数来说假设指数是ext,就表示用基数乘以2的exp次方:
- 0xFp2表示15乘以2的2次方,或者60.0
- 0xFp-2表示15乘以2的-2次方,或者3.75
以下的几个浮点数字面量都是十进制的12.1875
let decimalDouble = 12.1875
let exponentDouble = 1.21875e1
let hexadecimalDouble = 0xC.3p0
数字字面值还能加一些其它的格式让人更easy看懂。整数和浮点数都能在前面加入额外的0,还能加入下划线。
这些格式都不会影响字面量的值。
8.数字类型转换
要存储数字的时候尽量都用Int,即便是你知道要存储的值不会是负数。假设你每次都用默认的整型类型来定义常量和变量,这样你定义的这些变量跟常量的类型就能跟字面值判断出来的类型一样了。代码通用性就非常强。
仅仅有当你必需要用其它类型的整型的时候才去用。比方要在代码上用确切位数来保证性能。或者内存优化或者其它必要的优化。使用指定长度的类型能够帮助你避免一些不小心的值溢出。也能够为数据提供一份隐式的说明。
整型转换
对于整型常量或者变量,不一样的数字类型能存储的数据范围是不同的。Int8类型能存储的范围是-128到127,UInt8能够存储的范围是0到255。赋值的时候假设数据超出这个范围内,编译器会报错。
let cannotBeNegative: UInt8 = -1
// UInt8类型不能存储负数,所以会报错。
UInt8 cannot store negative numbers, and so this will report an error let tooBig: Int8 = Int8.max + 1 //
Int8 不能存储超过最大值得数字,所以这里也会报错。Int8 cannot store a number larger than its maximum value,
// and so this will also report an error 由于各种数字类型能存储的数据范围不同。所以你就必需要依据详细情况来进行类型转换了。这样能防止隐式转换的错误,还能让代码里的类型转换意图变得清晰。
要转换成其它类型。你须要实例化一个须要转换的类型的实例而且用现有的值给他初始化。拿上面的样例来说。常量twoThousand是UInt6类型,而常量one是UInt8类型,由于类型不一样所以两个常量不能直接相加。以下样例用UInt16(one)来创建一个UInt16类型的实例并用one来初始化。然后用这个值跟twoThousand相加。
let twoThousand: UInt16 = 2_000 let one: UInt8 = 1 let twoThousandAndOne = twoThousand + UInt16(one)
如今加号两边都是UInt16了,所以不会报错了。由于相加的和是UInt16型的,所以常量twoThousandAndOne也是UInt16类型。类型(值)是调用类型的初始化器并传入一个初始值的默认方式。当然这须要有个前提。就是UInt16有一个接受UInt8參数的初始化器,所以才干用这个方式来用UInt8创建UInt16。
所以这里你不能随便传其它类型的,必须是UInt16提供了对应的初始化器的才行。
拓展现有的初始化器。加入新的类型參数支持(例如说要支持自定义的类型)在后面的扩展部分里会介绍。
整型和浮点型的转换
整型和浮点型之间转换必需要显式转换。
这个样例中常量three的被用来创建另外一个Double类型。这样加号两边的类型才一样。假设不转换,是不能相加的。let three = 3 let pointOneFourOneFiveNine = 0.14159 let pi = Double(three) + pointOneFourOneFiveNine // pi=3.14159,所以pi被判断出来时Double类型。pi equals 3.14159, and is inferred to be of type Double
反过来也是一样的,Double或者Float类型的值也能够用来初始化一个整型的值。
let integerPi = Int(pi) // integerPi equals 3, and is inferred to be of type Int
用浮点数来初始化整型数的时候小数部分都会被阉割,例如说4.75转换变成4,-3.9转换变成-3。
NOTE 数字变量或者常量相加的规则跟数字字面量相加规则是不一样的(还记得前面有个3+0.14159吗)。字面量3能够直接跟字面量0.14159相加,由于字面量本身还没有一个确切的类型,仅仅有当编译器计算和的时候才会去判断字面量的类型。
9.类型别名类型别名是指使用现有类型的第二种方式。
类型别名使用keywordtypealias来定义。
当你想用更合适的方式来使用现有的类型的时候。类型别名就派上用场了。
例如说你要在外部代码中使用指定长度的数据。
typealias AutioSample = UInt16
仅仅要你定义了类型别名。那其它仅仅要能用原名的地方都能用别名。
var maxAmplitudeFound = AudioSample.min // maxAmplitudeFound is now 0
上面样例AudioSample被定义成是UInt16的别名,所以调用AudioSample.min实际上就是调用UInt16.min。10.布尔型
Swift有一个主要的布尔类型,叫Bool。布尔值是一种逻辑值,要么是true要么是false。Swift提供了两个布尔的常量值。没错。你猜对了,true和false。
let orangesAreOrange = true let turnipsAreDelicious = false
上面样例中两个常量分别用值true和false来初始化,所以编译器给他们判断出来的类型就是Bool。跟前面声明的Int和Double变量一样。这里你也不须要特别指明是Bool型。当然须要你在创建的时候用true或者false给他们初始化哦。
类型判断要让常量或者变量在创建的时候用还有一个类型已知的值来初始化,这让Swift的代码非常easy介绍也非常明了。
当你使用if之类的条件推断语句的时候布尔值就显得非常须要了。
if turnipsAreDelicious { println("Mmm, tasty turnips!") } else { println("Eww, turnips are horrible.") } // prints "Eww, turnips are horrible."
条件推断语句在后面流程控制里面会细讲。Swift的类型安全机制会保证不能再须要Bool值得地方用其它类型的值来取代。以下的样例就会报错。
let i = 1 if i { // this example will not compile, and will report an error }
以下这样写才是对的。let i = 1 if i == 1 { // this example will compile successfully }
i==1的比較结果是Bool类型的,所以另外一种方式能够通过类型安全检測,类似i==1这种比較运算会在后面的基本运算里介绍。
跟其它的类型安全的样例一样。这个也能避免一些偶然的错误,保证代码的意思清晰明了。
11.元组
元组能把好几个值放在一起组成一个复合值。元组里面的值能够是不论什么类型,各个值还不须要类型同样。举个样例。(404, "NotFound")这个元组用来表示一个HTTP状态码。
HTTP状态码是指你向一个HTTPserver请求页面的时候server返回的一个特殊值,假设你请求的页面不存在,server就会返回404 Not Found。
let http404Error = (404, "Not Found") // http404Error is of type (Int, String), and equals (404, "Not Found")
(404, "NotFound")这个元组把Int和String结合在一起,返回的HTT状态码有两个值:一个数字,和一段人能看懂的描写叙述。它能够被称为是类型为(Int, String)的元组。
你能够使用不论什么一组类型来创建元组。你想要不论什么不同的类型,都能满足你。没有什么能够阻挠你创建(Int, Int, Int)或者(String, Bool)或者不论什么其它的你想要的元组类型。
你能够把元组的数据解析出来存进常量或者变量。比方以下这样:
let (statusCode, statusMessage) = http404Error println("The status code is \(statusCode)") // prints "The status code is 404" println("The status message is \(statusMessage)") // prints "The status message is Not Found"
假设说你不须要某个位置的值,用下划线来替换那个位置的名字就OK了。let (justTheStatusCode, _) = http404Error println("The status code is \(justTheStatusCode)") // prints "The status code is 404"
或者你也能够用下标来获取元组里面的值。下标从0開始。
println("The status code is \(http404Error.0)") // prints "The status code is 404" println("The status message is \(http404Error.1)") // prints "The status message is Not Found"
创建元组的时候还能给里面的值命名。比方说let http200Status = (statusCode: 200, description: "OK")。假设这样创建的话。就能用名字来获取对应的值。
println("The status code is \(http200Status.statusCode)") // prints "The status code is 200" println("The status message is \(http200Status.description)") // prints "The status message is OK"
我经验不多,只是我感觉这东西跟JS的对象非常像啊。元组用来作为函数的返回值的时候特别实用。例如说有个检索页面的函数。返回(Int, String)类型的元组来表示检索页面成功还是失败。通过返回带有两个值的元组,就能比仅仅返回单个值的函数提供很多其它信息。很多其它介绍,请查看多返回值函数。
NOTE 元组对于临时组装一些相关的数据很实用。他不须要你去定义一些复杂的数据结构。
假设你的数据结果不仅仅是临时使用例如说还得存盘。这个时候使用创建一个类或者结果体会更合适。很多其它相关信息请查阅类和结构。
12.可选值
假设说某个值有可能不存在,那你能够使用可选值,可选值表示这里有个值等于多少多少,或者说这里没有值。
NOTE C跟OC里面是不存在可选值的概念的。
OC里面跟可选值最接近的特性就是方法要么返回nil要么返回对象。返回nil表示没有可用的对象。可是这仅仅针对对象有效,对于结构体。基本类型或者枚举类型是不适用的。对于这些类型,OC的方法返回了一个特别的值(比方说NSNotFound)来说明这里没有值。这样的方式要求调用方法的地方知道这里会返回特殊值。而且要记得去推断。Swift的可选值就没有类型的限制,也就不须要额外特殊额常量了。
这边有个样例,Swift的String类型有个方法叫做toInt。用来把字符串的值转换成Int值。
可是。并非全部的字符串都能转换成数字的,“123"能够转换成123可是”hello, china“显然是转不了的。
以下的样例就用toInt方法来吧String转换成Int:
let possibleNumber = "123" let convertedNumber = possibleNumber.toInt() // convertedNumber is inferred to be of type "Int?", or "optional Int"
由于toInt方法是有可能转换失败的,所以他返回的是一个可选的Int,而不是Int。可选Int类型用"Int?"表示而不是"Int"。问号表示这个值是可选的。也就是说变量里面有可能是某个Int值,也有可能什么都没有。(注意这里不可能包括其它比方Bool,或者String类型的值,要么是Int要么什么都没有。)
if语句和强行拆箱
你能够使用if语句来验证一个可选值是不是包括有值。假设有值。返回的是true。假设没有值返回的就是false。
假设你确定可选值有值,你能够在变量名后面加个感叹号来取得里面的值。感叹号的意思相当于:”小样儿我知道你带的有钱。交出来哥要用。“这个就是可选值强制拆箱。
if convertedNumber { println("\(possibleNumber) has an integer value of \(convertedNumber!)") } else { println("\(possibleNumber) could not be converted to an integer") } // prints "123 has an integer value of 123"
很多其它if语句的介绍。请參阅控制流。
NOTE 假设用感叹号去获取没有值的可选值,会发生执行时错误。一定要当你确定可选值有值的时候才使用感叹号。想想你鼓起勇气打劫了个穷光蛋。一毛钱没捞着还进去了。
可选值绑定
你也能够用可选值绑定来验证可选值里面是不是有值,通过这样的方式能够让可选值暂时存储在一个暂时的常量或者变量里。可选值绑定能够用在if或者while的条件语句中推断可选变量里面是不是有值,而且顺便把值取出来放到常量或者变量里面。
if跟while在控制流里面介绍。一般有点儿基础的应该都能够跳过了。
if中使用可选值绑定是以下这种
if let constantName = someOptional { statements }
那么上上面那个样例就能用可选值绑定来取代强制拆箱了。if let actualNumber = possibleNumber.toInt() { println("\(possibleNumber) has an integer value of \(actualNumber)") } else { println("\(possibleNumber) could not be converted to an integer") } // prints "123 has an integer value of 123"
代码翻译为:”假设possibleNumber.toInt返回的可选值里面有值。那么定义一个可选常量actualNumber,值就是方法返回的值“。
假设转换成功。常量actualNumber就能在if的大括号中面用了。并且actualNumber已经用转换方法返回的值初始化了,所以就没有必要再用感叹号去获取常量的值了。这个样例中actualNumber仅仅是简单的用来输出转换的结果。
在使用可选值绑定的时候能够用常量也能够用变量。假设你想在if第一个大括号中改动actualNumber的值,就用if var actualNumber取代,然后可选值包括的值就是个变量而不是常量了。
nil
假设你要把一个可选变量变成没有值的状态,给他赋值为ni就能够了。
var serverResponseCode: Int? = 404 // serverResponseCode contains an actual Int value of 404 serverResponseCode = nil // serverResponseCode now contains no value
NOTE nil不能用来给非可选变量或者常量赋值,假设某个变量或者常量有可能会没有值,一定要给他声明成相应的可选类型。记住是问号哦。
假设你定义一个可选常量或者变量的时候没有提供默认值,那他的值会被自己主动设为nil。
var surveyAnswer: String?
// surveyAnswer is automatically set to nil
NOTE Swift的nil跟OC里面的nil不太一样。在OC里面nil是一个不指向不论什么对象的指针,而在Swift里面nil不是指针,并且说这个地方没有值。不论什么类型都能用nil,而不不过对象类型。
隐式拆箱可选值
上面说的,可选值是说能够没有值的常量或者变量。
可选值能够用if语句来检測是不是有值,也能够用可选绑定来拆箱而且获取当中的值。
有时候有的可选值里面非常明显总是会有值的。在这样的情况下就没有必要每次使用的时候都去检查来拆箱获取值,由于我确定他总是会有值得。这样的可选值被称为隐式拆箱可选值。
定义这样的类型要在类型后面加感叹号,而不是问号。
当某个可选值被定义的时候就被赋值,并且以后都能确定他总是会有值。这个时候隐式拆箱可选值就能够使用。最開始使用隐式拆箱可选值的地方时在类初始化的地方。很多其它内容在无引用和隐式拆箱可选值属性里面介绍。
隐式拆箱可选值也就是一种可选值,可是还能像非可选值一样来使用。而不想要每次使用的时候都去拆箱。以下举个样例说明可选字符串与隐式拆箱可选字符串的差别。
let possibleString: String?
= "An optional string." println(possibleString!) // requires an exclamation mark to access its value // prints "An optional string." let assumedString: String! = "An implicitly unwrapped optional string." println(assumedString) // no exclamation mark is needed to access its value // prints "An implicitly unwrapped optional string."
你能够觉得隐式拆箱可选值是一种拥有自己主动拆箱权限的可选值。声明可选变量的时候类型后面加感叹号就是隐式拆箱可选变量,就不用每次使用的时候都在变量名后面加感叹号了。NOTE 假设你试图訪问一个没有值的隐式拆箱可选变量,会产生执行时错误,就像你在一个没有值得可选变量后面加个感叹号一样。
你还能够像使用普通可选值一样使用隐式产想可选值。比方说用If推断其是否有值
if assumedString { println(assumedString) } // prints "An implicitly unwrapped optional string."
NOTE 假设说可选值以后有可能会变成nil,就不要使用隐式拆箱可选。假设变量生命周期内有可能须要检測是否为nil就使用普通的可选。
13.断言(Assetions)
可选类型能够让你检測值是否存在,然后处理值不存在的情况。可是在有些情况下,假设值不存在就没办法进行,或者有值可是这个值不符合条件。这样的情况下你能够触发断言来结束运行,从而能够调试为什么值不存在。
使用断言调试
断言是指在运行期间检測一个逻辑值是否为true。也就是说断言断定那个条件是true。你能够使用断言来保证程序运行的时候仅仅有当满足了某个条件的时候才继续往下运行。假设条件表达式计算结果为true,程序照常运行,假设结果为false,就不再运行了,应用也就退出了。
假设你在调试环境中执行代码而且触发了断言,那你能够清楚的看到哪里的条件没通过,而且能够查看当断言触发的时候应用时什么状态。断言还能够接受你提供的一些调试信息。通过调用全局函数assert来使用断言。第一个參数须要是范围true或者false的表达式,第二个參数的信息能够在表达式返回false的时候输出。
let age = -3 assert(age >= 0, "A person's age cannot be less than zero") // this causes the assertion to trigger, because age is not >= 0
上面样例假设age>=0返回true的话代码还会继续运行,也就是说age是非负数的时候。假设age是负数,age>=0就是false了,这个时候断言就触发了,应用终止。注意第二个參数不能使用字符串填补。只是第二个參数能够省略,比方asset(age >= 0)
什么时候要用断言
假设说某个地方你一定须要满足什么条件才干继续运行的时候就能够用断言。当中包含下面场景:
在使用下标语法的时候数字下标的值不能太大也不能太小。
调用函数的时候假设传递非法參数函数就不能完毕任务。
有个可选值当时是nil,可是后面代码的运行须要他有值。
NOTE 当某些条件达不到的时候断言会让应用终止,让应用程序终止肯定不是最好的方式。可是在开发阶段还是保证那些条件被注意到的有效的方式。
要做到这一点,该产品没有被释放。
本章结束。下章地址: 4.基础运营商