// 常量和变量
//1.声明常量和变量
//常量和变量必须在使用前声明,用 let 来声明常量,用 var 来声明变量
let mixNumber = 2
var currentNumber = 3
//“你可以在一行中声明多个常量或者多个变量,用逗号隔开”
var x = 0.0 , y = 0.0 ,z = 0.0
//注意: “如果你的代码中有不需要改变的值,请使用 let 关键字将它声明为常量。只将需要改变的值声明为变量。”
//2. 类型标注
// 声明常量或者变量时可以加上类型标注(type annotation),名称后加上一个冒号和空格,然后加上类型名称
var welcomeMsg: String
//可以在一行中定义多个同样类型的变量,用逗号分隔,在最后一个变量名称后加上类型标注
var red,green,blue: String
//注意:“一般来说你很少需要写类型标注。如果你在声明常量或者变量的时候赋了一个初始值,Swift可以推断出这个常量或者变量的类型”
//3. 常量和变量的命名
//可以用你喜欢的字符作为常量和变量名,包括 Unicode 字符常量与变量名不能包含数学符号,箭头,保留的(或者非法的)Unicode 码位,连线与制表符。也不能以数字开头,但是可以在常量与变量名的其他地方包含数字
var color = "red"
let `let` = "something"
// 注意:“需要使用与Swift保留关键字相同的名称作为常量或者变量名,你可以使用反引号(`)将关键字包围的方式将其作为名字使用。无论如何,你应当避免使用关键字作为常量或变量名,除非你别无选择。“
//4. 输出常量和变量
//“print(_:separator:terminator:) 是一个用来输出一个或多个值到适当输出区的全局函数”
//“字符串插值(string interpolation)的方式把常量名或者变量名当做占位符加入到长字符串中”
print(mixNumber)
print("the current value of color is \(color)")
//5. 分号
// swift不强制要求在每条语句的结尾使用分号; 当然可以按照自己的习惯添加分号。 在一行内写多条独立的语句,需要用分号
let cat = "cat" ; print(cat)
//6.整数
// “Swift 提供了8,16,32和64位的有符号和无符号整数类型。这些整数类型和 C 语言的命名方式很像,比如8位无符号整数类型是UInt8,32位有符号整数类型是 Int32 。就像 Swift 的其他类型一样,整数类型采用大写命名法。”
let someValue: UInt8 = 10
// “你可以访问不同整数类型的 min 和 max 属性来获取对应类型的最小值和最大值”
let minValue = UInt8.min
let maxValue = UInt8.max
// Int
//一般不需要专门指定整数的长度。 swift提供一个特殊的整数类型Int,长度与当前平台的原生字长相同
//“在32位平台上,Int 和 Int32 长度相同。在64位平台上,Int 和 Int64 长度相同。
// 除非需要特定长度的整数,一般来说,使用Int就够了。
//UInt
// “在32位平台上,UInt 和 UInt32 长度相同。在64位平台上,UInt 和 UInt64 长度相同。”
//注意:“尽量不要使用UInt”“最好使用Int,即使你要存储的值已知是非负的。统一使用Int可以提高代码的可复用性,避免不同类型数字之间的转换,并且匹配数字的类型推断,”
// 7. 浮点数
// 浮点数是有小数部分的数字,如3.14 “Double表示64位浮点数。当你需要存储很大或者很高精度的浮点数时请使用此类型。Float表示32位浮点数。精度要求不高的话可以使用此类型。”
// 注意: “Double精确度很高,至少有15位数字,而Float只有6位数字”“在两种类型都匹配的情况下,将优先选择 Double。”
// 8. 类型安全和类型推断: *** 重要
//“ Swift 是类型安全的,所以它会在编译你的代码时进行类型检查(type checks),并把不匹配的类型标记为错误。这可以让你在开发的时候尽早发现并修复错误”
//“如果你没有显式指定类型,Swift 会使用类型推断(type inference)来选择合适的类型。有了类型推断,编译器可以在编译代码的时候自动推断出表达式的类型。原理很简单,只要检查你赋的值即可”
//“当你声明常量或者变量并赋初值的时候类型推断非常有用。当你在声明常量或者变量的时候赋给它们一个字面量(literal value 或 literal)即可触发类型推断。(字面量就是会直接出现在你代码中的值,比如 42 和 3.14159 。)”
//“当推断浮点数的类型时,Swift 总是会选择 Double 而不是Float。如果表达式中同时出现了整数和浮点数,会被推断为 Double 类型
//9. 数值型字面量
// “一个十进制数, 没有前缀一个二进制数,前缀是0b 一个八进制数,前缀是0o 一个十六进制数,前缀是0x”
//10. 数值型类型转换
// “通常来讲,即使代码中的整数常量和变量已知非负,也请使用Int类型。总是使用默认的整数类型可以保证你的整数常量和变量可以直接被复用并且可以匹配整数类字面量的类型推断。”“只有在必要的时候才使用其他整数类型”
//“如果数字超出了常量或者变量可存储的范围,编译的时候会报错”
// “SomeType(ofInitialValue) 是调用 Swift 构造器并传入一个初始值的默认方法。在语言内部,UInt16 有一个构造器,可以接受一个UInt8类型的值,所以这个构造器可以用现有的 UInt8 来创建一个新的 UInt16。注意,你并不能传入任意类型的值,只能传入 UInt16 内部有对应构造器的值。”
let twoThousand: UInt16 = 2000
let one: UInt8 = 1
let twothousandAndOne = twoThousand + UInt16(one)
//11. 整数和浮点类型转换
//“整数和浮点数的转换必须显式指定类型:”
let three = 3
let pointOneFour = 0.14
let pi = Double(three) + pointOneFour
//pi被推测为Double类型
let intPi = Int(pi)
//“当用这种方式来初始化一个新的整数值时,浮点值会被截断。也就是说 4.75 会变成 4,-3.9 会变成 -3。”
//12.类型别名
//“类型别名(type aliases)就是给现有类型定义另一个名字。你可以使用typealias关键字来定义类型别名。当你想要给现有类型起一个更有意义的名字时,类型别名非常有用”
typealias AudioSample = UInt16
var maxAmplitudeFound = AudioSample.max
//13. 布尔值
//Swift 有一个基本的布尔(Boolean)类型,叫做Bool。布尔值指逻辑上的值,因为它们只能是真或者假。Swift 有两个布尔常量,true 和 false
let orangesAreOrange = true
let turnipsAreDelicious = false
let i = 1
//if i {
//
//} 会报错
if i == 1 {
}
//14.元组, tuples
// 把多个值组合成一个复合值,元组内的值可以是任意类型
let http404Error = (404,"Not Found")
//可以将一个元组的内容分解成单独的常量和变量,正常使用
let (statusCode,statusMessage) = http404Error
print("the status code is \(statusCode), and the Message is \(statusMessage)")
//“你只需要一部分元组值,分解的时候可以把要忽略的部分用下划线(_)标记:”
let (justTheStatusCode,_) = http404Error
print("th status code is \(justTheStatusCode)")
//可以通过下标来范文元组中的单个元素
print("the status code is \(http404Error.0)")
//可以在定义元组的时候,给单个元素命名
let http200Status = (statusCode:200,description:"ok")
print("the status code is \(http200Status.statusCode)")
// “作为函数返回值时,元组非常有用。一个用来获取网页的函数可能会返回一个 (Int, String) 元组来描述是否获取成功。和只能返回一个类型的值比较起来,一个包含两个不同类型值的元组可以让函数的返回信息更有用。”
// 注意: 元组在类似组织值的时候很有用,但是并不时候创建复杂的数据结构
//15. 可选类型 *** 重要
// “使用可选类型(optionals)来处理值可能缺失的情况。可选类型表示:
/*
有值,等于 x
或者
没有值
*/
//“最接近的是 Objective-C 中的一个特性,一个方法要不返回一个对象要不返回nil,nil表示“缺少一个合法的对象”。然而,这只对对象起作用——对于结构体,基本的 C 类型或者枚举类型不起作用。对于这些类型,Objective-C 方法一般会返回一个特殊值(比如NSNotFound)来暗示值缺失。这种方法假设方法的调用者知道并记得对特殊值进行判断。”
let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
//print(convertedNumber)
// convertedNumber 的类型为 int? 或者 OPtional Int
//“你可以给可选变量赋值为nil来表示它没有值”
var serverResponseCode: Int? = 404
// serverResponseCode 包含一个可选的 Int 值 404
serverResponseCode=nil
//serverResponseCode 现在不包含值
// 注意:“nil不能用于非可选的常量和变量。如果你的代码中有常量或者变量需要处理值缺失的情况,请把它们声明成对应的可选类型。”
//“如果你声明一个可选常量或者变量但是没有赋值,它们会自动被设置为 nil:”
var surverAnswer:String?
//surverAnswer被自动设置为nil
//注意: “Swift 的 nil 和 Objective-C 中的 nil 并不一样。在 Objective-C 中,nil 是一个指向不存在对象的指针。在 Swift 中,nil 不是指针——它是一个确定的值,用来表示值缺失。任何类型的可选状态都可以被设置为 nil,不只是对象类型。”
//16.if语句以及强制解析
//“你可以使用 if 语句和 nil 比较来判断一个可选值是否包含值。你可以使用“相等”(==)或“不等”(!=)来执行比较。”
if convertedNumber != nil {
print(" convertedNumber contain some integer value")
}
//“当你确定可选类型确实包含值之后,你可以在可选的名字后面加一个感叹号(!)来获取值。这个惊叹号表示“我知道这个可选有值,请使用它。”这被称为可选值的强制解析(forced unwrapping):”
if convertedNumber != nil {
print("convertedNumber contain an integer value of \(convertedNumber!)")
}
// 注意:“使用 ! 来获取一个不存在的可选值会导致运行时错误。使用 ! 来强制解析值之前,一定要确定可选包含一个非 nil 的值。”
// 17. if语句与可选绑定
//“使用可选绑定(optional binding)来判断可选类型是否包含值,如果包含就把值赋给一个临时常量或者变量。可选绑定可以用在 if 和 while 语句中,这条语句不仅可以用来判断可选类型中是否有值,同时可以将可选类型中的值赋给一个常量或者变量”
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 语句的第一个分支中使用。它已经被可选类型 包含的 值初始化过,所以不需要再使用 ! 后缀来获取它的值”
//“你可以在可选绑定中使用常量和变量。如果你想在if语句的第一个分支中操作 actualNumber 的值,你可以改成 if var actualNumber,这样可选类型包含的值就会被赋给一个变量而非常量。”
//“你可以包含多个可选绑定或多个布尔条件在一个 if 语句中,只要使用逗号分开就行。只要有任意一个可选绑定的值为nil,或者任意一个布尔条件为false,则整个if条件判断为false,这时你就需要使用嵌套 if 条件语句来处理”
if let firstNumber = Int("4") {
if let secondNumber = Int("42") {
if firstNumber<secondNumber && secondNumber < 100 {
print("\(firstNumber) < \(secondNumber) ")
}
}
}
// 使用if语句的可选绑定可以用来解析值
// 18. 隐式解析可选类型
//“第一次被赋值之后,可以确定一个可选类型总会有值。在这种情况下,每次都要判断和解析可选值是非常低效的,因为可以确定它总会有值。”
//“这种类型的可选状态被定义为隐式解析可选类型(implicitly unwrapped optionals)。把想要用作可选的类型的后面的问号(String?)改成感叹号(String!)来声明一个隐式解析可选类型。”
//“隐式解析可选类型主要被用在 Swift 中类的构造过程中”
//“一个隐式解析可选类型其实就是一个普通的可选类型,但是可以被当做非可选类型来使用,并不需要每次都使用解析来获取可选值”
//普通可选类型
let possibleString: String? = "An Optianl String"
let forcedString: String = possibleString!
//隐式解析可选类型
let assumeString: String! = "An implicitly unwrapped optional string"
let implicitString: String = assumeString
//“你可以把隐式解析可选类型当做一个可以自动解析的可选类型。你要做的只是声明的时候把感叹号放到类型的结尾,而不是每次取值的可选名字的结尾。”
//注意:“如果你在隐式解析可选类型没有值的时候尝试取值,会触发运行时错误。和你在没有值的普通可选类型后面加一个惊叹号一样。”
// “你仍然可以把隐式解析可选类型当做普通可选类型来判断它是否包含值:”
if assumeString != nil{
print(assumeString)
}
//“你也可以在可选绑定中使用隐式解析可选类型来检查并解析它的值”
if let definiteString = assumeString {
print(definiteString)
}
//注意: “如果一个变量之后可能变成nil的话请不要使用隐式解析可选类型。如果你需要在变量的生命周期中判断是否是nil的话,请使用普通可选类型”
//19:错误处理
// “相对于可选中运用值的存在与缺失来表达函数的成功与失败,错误处理可以推断失败的原因,并传播至程序的其他部分”
// “一个函数可以通过在声明中添加throws关键词来抛出错误消息。当你的函数能抛出错误消息时, 你应该在表达式中前置try关键词。”
func canThrowAnError()throws {
//函数在执行的时候,可能抛出错误
}
do {
try canThrowAnError()
//没有错误抛出,继续往下走
} catch {
// 有错误抛出,走catch。
}
// 20.断言 *** 听着蛮高大上的,
//“断言会在运行时判断一个逻辑条件是否为 true。从字面意思来说,断言“断言”一个条件是否为真。你可以使用断言来保证在运行其他代码之前,某些重要的条件已经被满足。如果条件判断为 true,代码运行会继续进行;如果条件判断为 false,代码执行结束,你的应用被终止。”
let age = 3
assert(age >= 0, "A person's age cannot be less than zero")
//“当条件可能为假时使用断言,但是最终一定要保证条件为真,这样你的代码才能继续运行。断言的适用情景:
//整数类型的下标索引被传入一个自定义下标实现,但是下标索引值可能太小或者太大。
//需要给函数传入一个值,但是非法的值可能导致函数不能正常执行。
//一个可选值现在是 nil,但是后面的代码运行需要一个非 nil 值。
//断言用于调试