Swift4.1学习笔记(更新中)
一.swift的声明。
常量声明使用let,var来声明变量。
var friendlyWelcome ="Hello!"
friendlyWelcome ="Bonjour!"
Note:常量一旦初始化很难改的。
二.类型的标注。
var welcomeMessage:String
var red, green,blue: Double
Note:一般来说你很少需要写类型标注,系统可自动推测出来。
三.输出常量和变量。
// 输出"Bonjour!"
print(friendlyWelcome)
// 输出 "The current value of friendlyWelcome is Bonjour!
print("The current value of friendlyWelcome is \(friendlyWelcome)")
四.分号。
Swift 并不强制要求你在每条语句的结尾处使用分号。
有一种情况下必须要用分号,即你打算在同一行内写多条独立的语句:
let cat ="";
// 输出""
print(cat)/
五.整数。
Swift 提供了8,16,32和64位的有符号和无符号整数类型。这些整数类型和 C 语言的命名方式很像,比如8位无符号整数类型是UInt8。
除非你需要特定长度的整数,一般来说使用 Int就够了。这可以提高代码一致性和可复用性。即使是在32位平台上,Int 可以存储的整数范围也可以达到 -2,147,483,648 ~ 2,147,483,647,大多数时候这已经足够大了。
六.UInt。
Swift 也提供了一个特殊的无符号类型 UInt,长度与当前平台的原生字长相同.
Note:尽量不要使用UInt,除非你真的需要存储一个和当前平台原生字长相同的无符号整数。建议使用int。
七.浮点数。
Double表示64位浮点数。
Float表示32位浮点数。
Note:Double精确度很高,至少有15位数字,而Float只有6位数字。
类型安全和类型推断
八.Swift 是一个类型安全(type-safe)的语言。类型安全的语言可以让你清楚地知道代码要处理的值的类型。如果你的代码需要一个String,你绝对不可能错误地传进去一个Int。
由于 Swift 是类型安全的,所以它会在编译你的代码时进行类型检查(type checks),并把不匹配的类型标记为错误。这可以让你在开发的时候尽早发现并修复错误。
九.整数转换。
不同整数类型的变量和常量可以存储不同范围的数字。Int8类型的常量或者变量可以存储的数字范围是-128~127,而UInt8类型的常量或者变量能存储的数字范围是0~255。如果数字超出了常量或者变量可存储的范围,编译的时候会报错:
为了将一种数字类型转换成另一种,你要用当前值来初始化一个期望类型的新数字,这个数字的类型就是你的目标类型。在下面的例子中,常量twoThousand是UInt16类型,然而常量one是UInt8类型。它们不能直接相加,因为它们类型不同。所以要调用UInt16(one)来创建一个新的UInt16数字并用one的值来初始化,然后使用这个新数字来计算:
let twoThousand: UInt16 = 2_000
let one: UInt8 = 1
let twoThousandAndOne = twoThousand + UInt16(one)
十.整数和浮点数转换。
整数和浮点数的转换必须显式指定类型:
let three =3
let pointOneFourOneFiveNine =0.14159
let pi = Double(three) + pointOneFourOneFiveNine
这个例子中,常量 three的值被用来创建一个Double类型的值,所以加号两边的数类型须相同。如果不进行转换,两者无法相加。浮点数到整数的反向转换同样行,整数类型可以用`` Double或者Float`类型来初始化:
letintegerPi = Int(pi)
当用浮点类型来初始化一个新的整数值时,浮点值会被截断。也就是说 4.75会变成 4,-3.9会变成 -3。
Note:结合数字类常量和变量不同于结合数字类字面量。字面量3可以直接和字面量0.14159相加,因为数字字面量本身没有明确的类型。它们的类型只在编译器需要求值的时候被推测。
十一.类型别名
类型别名type aliases就是给现有类型定义另一个名字。你可以使用typealias关键字来定义类型别名。
typealias AudioSample =UInt16
定义了一个类型别名之后,你可以在任何使用原始名的地方使用别名:
varmaxAmplitudeFound = AudioSample.min// maxAmplitudeFound 现在是 0
十二.布尔值
letorangesAreOrange = true
let turnipsAreDelicious =false
if turnipsAreDelicious
{
print("Mmm, tasty turnips!")
}else{
print("Eww, turnips are horrible.")
}// 输出 "Eww, turnips are horrible."
十三.元组
元组把多个值合并成单一的复合型的值。元组内的值可以是任何类型,而且可以不必是同一类型。
lethttp404Error=(404,"Not Found")
任何类型的排列都可以被用来创建一个元组,他可以包含任意多的类型。例如(Int,Int,Int) 或者(String,Bool) ,实际上,任何类型的组合都是可以的。
你也可以将一个元组的内容分解成单独的常量或变量,这样你就可以正常的使用它们了:
let(statusCode,statusMessage)= http404Error
print("The status code is \(statusCode)")
// prints "The status code is 404"
当你分解元组的时候,如果只需要使用其中的一部分数据,不需要的数据可以用下滑线(_ )代替:
let (justTheStatusCode, _)= http404Error
print("The status code is \(justTheStatusCode)")
// prints "The status code is 404"
另外一种方法就是利用从零开始的索引数字访问元组中的单独元素:
print("The status code is \(http404Error.0)")
你可以在定义元组的时候给其中的单个元素命名:
let http200Status=(statusCode:200,description:"OK")
在命名之后,你就可以通过访问名字来获取元素的值了:
print("The status code is \(http200Status.statusCode)")
作为函数返回值时,元组非常有用。一个用来获取网页的函数可能会返回一个(Int,String)元组来描述是否获取成功。相比只能返回一个类型的值,元组能包含两个不同类型值,他可以让函数的返回信息更有用。更多内容请参考多返回值的函数。
Note:元组在临时的值组合中很有用,但是它们不适合创建复杂的数据结构。如果你的数据结构超出了临时使用的范围,那么请建立一个类或结构体来代替元组。更多信息请参考类和结构体。
十四.可选项
可以利用可选项来处理值可能缺失的情况。可选项意味着:
这里有一个值,他等于x或者这里根本没有值
Swift 的Int 类型中有一个初始化器,可以将String 值转换为一个Int 值。然而并不是所有的字符串都可以转换成整数。字符串“123” 可以被转换为数字值123 ,但是字符串"hello, world" 就显然不能转换为一个数字值。
let possibleNumber= "123"
let convertedNumber =Int(possibleNumber)
十五.nil
你可以通过给可选变量赋值一个nil 来将之设置为没有值:
var serverResponseCode:Int?=404
serverResponseCode=nil
如果你定义的可选变量没有提供一个默认值,变量会被自动设置成nil
varsurveyAnswer:String?
十六.If 语句以及强制展开
if convertedNumber !=nil{
print("convertedNumber has an integer value of \(convertedNumber!).")
}
note:使用! 来获取一个不存在的可选值会导致运行错误,在使用!强制展开之前必须确保可选项中包含一个非nil 的值。
十七.可选项绑定
可以使用可选项绑定来判断可选项是否包含值,如果包含就把值赋给一个临时的常量或者变量。可选绑定可以与if 和while 的语句使用来检查可选项内部的值,并赋值给一个变量或常量。if 和while 语句的更多详细描述,请参考控制流。
if let constantName=someOptional{
statements
}
你可以像上面这样使用可选绑定而不是强制展开来重写possibleNumber 这个例子:
if let actualNumber=Int(possibleNumber){
print("\'\(possibleNumber)\' has an integer value of \(actualNumber)")
}else{
print("\'\(possibleNumber)\' could not be converted to an integer")
}
如果Int(possibleNumber) 返回的可选Int 包含一个值,将这个可选项中的值赋予一个叫做actualNumber 的新常量。
如果转换成功,常量actualNumber 就可以用在if 语句的第一个分支中,他早已被可选内部的值进行了初始化,所以这时就没有必要用! 后缀来获取里边的值。在这个栗子中actualNumber 被用来输出转换后的值。
常量和变量都可以使用可选项绑定,如果你想操作if 语句中第一个分支的actualNumber 的值,你可以写ifvaractualNumber 来代替,可选项内部包含的值就会被设置为一个变量而不是常量。
你可以在同一个if 语句中包含多可选项绑定,用逗号分隔即可。如果任一可选绑定结果是nil 或者布尔值为false ,那么整个if 判断会被看作false 。下面的两个if 语句是等价的:
// Prints "4 < 42 < 100"
if let firstNumber=Int("4"),letsecondNumber=Int("42"),firstNumber
print("\(firstNumber)< \(secondNumber)< 100")
}
if let firstNumber=Int("4"){
if let secondNumber=Int("42"){
if firstNumber
print("\(firstNumber)< \(secondNumber)< 100")
}
}
}
note:如同提前退出中描述的那样,使用if 语句创建的常量和变量只在if语句的函数体内有效。相反,在guard 语句中创建的常量和变量在guard 语句后的代码中也可用。
十八.隐式展开可选项
如上所述,可选项明确了常量或者变量可以“没有值”。可选项可以通过if 语句来判断是否有值,如果有值的话可以通过可选项绑定来获取里边的值。
有时在一些程序结构中可选项一旦被设定值之后,就会一直拥有值。在这种情况下,就可以去掉检查的需求,也不必每次访问的时候都进行展开,因为它可以安全的确认每次访问的时候都有一个值。
这种类型的可选项被定义为隐式展开可选项。通过在声明的类型后边添加一个叹号(String! )而非问号( String? ) 来书写隐式展开可选项。
在可选项被定义的时候就能立即确认其中有值的情况下,隐式展开可选项非常有用。如同无主引用和隐式展开的可选属性中描述的那样,隐式展开可选项主要被用在 Swift 类的初始化过程中。
隐式展开可选项是后台场景中通用的可选项,但是同样可以像非可选值那样来使用,每次访问的时候都不需要展开。下面的例子展示了在访问被明确为String 的可选项展开值时,可选字符串和隐式展开可选字符串的行为区别:
let possibleString:String?="An optional string."
let forcedString:String=possibleString!// requires an exclamation mark
let assumedString:String!="An implicitly unwrapped optional string."
let implicitString:String=assumedString// no need for an exclamation mark
你可以把隐式展开可选项当做在每次访问它的时候被给予了自动进行展开的权限,你可以在声明可选项的时候添加一个叹号而不是每次调用的时候在可选项后边添加一个叹号。
note:如果你在隐式展开可选项没有值的时候还尝试获取值,会导致运行错误。结果和在没有值的普通可选项后面加一个叹号一样。
// prints "An implicitly unwrapped optional string."
if assumedString!=nil{
print(assumedString)
}
你也可以使用隐式展开可选项通过可选项绑定在一句话中检查和展开值:
// prints "An implicitly unwrapped optional string."
if let definiteString=assumedString{
print(definiteString)
}
note:不要在一个变量将来会变为nil 的情况下使用隐式展开可选项。如果你需要检查一个变量在生存期内是否会变为nil ,就使用普通的可选项。
十九. 错误处理
比于可选项的通过值是否缺失来判断程序的执行正确与否,而错误处理机制能允许你判断错误的形成原因,在必要的情况下,还能将你的代码中的错误传递到程序的其他地方。
当一个函数遇到错误情况,他会抛出一个错误,这个函数的访问者会捕捉到这个错误,并作出合适的反应。
func canThrowAnError() throws{
// this function may or may not throw an error
}
通过在函数声明过程当中加入throws 关键字来表明这个函数会抛出一个错误。当你调用了一个可以抛出错误的函数时,需要在表达式前预置try 关键字。
Swift 会自动将错误传递到它们的生效范围之外,直到它们被catch 分句处理。
do{
trycanThrowAnError()
// no error was thrown
}catch{
// an error was thrown
}
do 语句创建了一个新的容器范围,可以让错误被传递到到不止一个的catch 分句里。
下面的例子演示了如何利用错误处理机制处理不同的错误情况:
func makeASandwich() throws{
// ...
}
do{
trymakeASandwich()
eatASandwich()
}catchError.OutOfCleanDishes{
washDishes()
}catchError.MissingIngredients(letingredients){
buyGroceries(ingredients)
}
在上面的例子中,在没有干净的盘子或者缺少原料的情况下,方法makeASandwich() 就会抛出一个错误。由于makeASandwich() 的抛出,方法的调用被包裹在了一个try 的表达式中。通过将方法的调用包裹在do 语句中,任何抛出来的错误都会被传递到预先提供的catch 分句中。
如果没有错误抛出,方法eatASandwich() 就会被调用,如果有错误抛出且满足Error.OutOfCleanDishes 这个条件,方法washDishes() 就会被执行。如果一个错误被抛出,而它又满足Error.MissingIngredients 的条件,那么buyGroceries(_:) 就会协同被catch 模式捕获的[String] 值一起调用。
有关抛出,捕获和错误传递的更详细信息请参考错误处理。