//: Playground - noun: a place where people can play
import UIKit
// # 常量和变量
// 在一行中声明多个变量或常量,用逗号分隔
var x = 0, y = 0.0, z = "dfd"
// 类型标注
var welcomeMessage: String
welcomeMessage = "Hello"
// trick: 多个同类型变量
var red, green, blue: Double
// 输出全局函数: print(<#T##items: Any...##Any#>, separator: <#T##String#>(默认值是空格), terminator: <#T##String#>(默认值是换行))
// # 注释
// # 分号
// # 整数
// 用.min, .max访问类型的最小最大值,这是一个static的只读变量
print(UInt8.min)
// # 浮点数
// # 类型安全和类型推断
// 字面量3和7都被推断为Double,如果不是字面量会报错。换言之,字面量 3 可以直接和字面量 0.14159 相加,因为数字字面量本身没有明确的类型。它们的类型只有在编译器需要计算的时候才会被推测出来。
var result = (3 + 2.1) / 7
// # 数值型字面量
// 1.25e2意味着125.0,1.25e-2意味着0.0125
// trick: 整数和浮点数都可以添加额外的零或者添加下划线来增加代码的可读性。下面的这些格式都不会影响字面量的值。
let paddedDouble = 000123.456
let oneMillion = 1_000_000
let justOverOneMillion = 1_000_000.000_000_1
// # 数值类型转换
// 拓展Int使其支持类型转换。要注意Int中self的用法。
class Binary {
var first = 0
var secend = 0
}
extension Int {
init(_ binary: Binary) {
self = binary.first * 2 + binary.secend
}
}
var binary = Binary()
print(Int(binary))
// 在用浮点数初始化一个新的整数类型的时候,数值会被截断。也就是说 4.75 会变成 4 , -3.9 会变为 -3 。
// # 类型别名
typealias Student = Int
let tom = Student(8)
let jerry = Int(3)
// # 布尔值
// # 元组
// 是值类型
// 元组可以合起来使用
let coupleOne = ("James", "Marry")
print(coupleOne)
print(coupleOne.0)
// 也可以分开使用,又叫拆分,是单独提取元组元素时用
let (husband, wife) = ("Bob", "Lily")
print("The husband is \(husband)")
// trick: 拆分过程中不需要的用_代替
let (anotherHusband, _) = ("Kevin", "Sophia")
print(anotherHusband)
// 调整内部名,也可以就用默认.0, .1等访问。注意这并非是拆分了元组,不能直接用新名字。另外可以看到,coupleFour的类型为(fourthHusband: String, fourthWife: String)而不是(String, String),有本质区别
let coupleFour = (fourthHusband: "King", fourthWife: "Darling")
print(coupleFour.1)
print(coupleFour.fourthHusband)
// # 可选项
// trick: String转换为Int的初始化器,返回一个Int?
let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
var sir: String? // var类型可选被自动设值为nil
let shemale: String? // let类型可选不会被隐式初始化为nil
shemale = "Jack" // 此时被初始化,此后不能再改变其值
var lady: String? = "Sophia"
// 在类型中,也可以得到体现
class Dog {
var name: String? // 若为let,会报错并提示init未对其初始化
var color: String
init(ofColor color: String) {
self.color = color
}
}
// 用if判断然后强制展开,好处是不用多令一个常量并且保证安全
if convertedNumber != nil {
print("convertedNumber contains some intrgar value and it's \(convertedNumber!)")
}
// 可选项绑定,可用于if和while语句,好处是可以多一个变量来使用可选包含的量并且安全。注意,控制流里定义的变量在之后消失 while let???
if let actualNumber = Int(possibleNumber) {
print("\'\(possibleNumber)\' has an integer value of \(actualNumber)")
} else {
print("\'\(possibleNumber)\' could not be converted to an integer")
}
// trick: 在同一个if语句中包含多个可选项绑定和布尔运算,用逗号隔开,相当于“与”运算。
if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber, secondNumber < 100 {
print("\(firstNumber) < \(secondNumber) < 100")
}
// 隐式展开可选项:既不用写所在类的初始化器,又不用麻烦地每次强制展开。也可以用if判断或者用可选项绑定
var assumedString: String!
assumedString = "OK"
assumedString = nil
// trick: 不要在一个变量将来会变为 nil 的情况下使用隐式展开可选项。这样有些危险,不如用普通可选项了。
// ??:合并空值运算符
var flag: Bool?
var shitIsGood = flag ?? false
print(shitIsGood)
// # 错误处理
// 函数声明过程加上throws关键字
func makeASandwich() throws {
}
// 调用函数时,在表达式前置try关键字。do语句创建容器范围,可让错误传递到catch分句
/*
do {
try makeASandwich()
// 如果没有错误,则调用
eatASandwich()
} catch Error.OutOfCleanDishes {
washDishes()
} catch Error.MissingIngredients(let ingredients) {
buyGroceries(ingredients)
}
*/
// # 断言和先决条件
// 断言:一个从宏观角度检查程序的全局函数,并且只在调试阶段触发
let age = 3
assert(age >= 0, "A person's age cannot be less than zero")
// 直接断言
if age >= 0 {
print("You are human now")
} else {
assertionFailure("A person's age cannot be less than zero")
}
// 先决条件,差不多,具体差异???
precondition(age >= 0, "A person's age cannot be less than zero")
// fatalError(_:file:line:)也差不多,只是不用执行检查罢了
//: Playground - noun: a place where people can play
import UIKit
// # 常量和变量
// 在一行中声明多个变量或常量,用逗号分隔
var x = 0, y = 0.0, z = "dfd"
// 类型标注
var welcomeMessage: String
welcomeMessage = "Hello"
// trick: 多个同类型变量
var red, green, blue: Double
// 输出全局函数: print(<#T##items: Any...##Any#>, separator: <#T##String#>(默认值是空格), terminator: <#T##String#>(默认值是换行))
// # 注释
// # 分号
// # 整数
// 用.min, .max访问类型的最小最大值,这是一个static的只读变量
print(UInt8.min)
// # 浮点数
// # 类型安全和类型推断
// 字面量3和7都被推断为Double,如果不是字面量会报错。换言之,字面量 3 可以直接和字面量 0.14159 相加,因为数字字面量本身没有明确的类型。它们的类型只有在编译器需要计算的时候才会被推测出来。
var result = (3 + 2.1) / 7
// # 数值型字面量
// 1.25e2意味着125.0,1.25e-2意味着0.0125
// trick: 整数和浮点数都可以添加额外的零或者添加下划线来增加代码的可读性。下面的这些格式都不会影响字面量的值。
let paddedDouble = 000123.456
let oneMillion = 1_000_000
let justOverOneMillion = 1_000_000.000_000_1
// # 数值类型转换
// 拓展Int使其支持类型转换。要注意Int中self的用法。
class Binary {
var first = 0
var secend = 0
}
extension Int {
init(_ binary: Binary) {
self = binary.first * 2 + binary.secend
}
}
var binary = Binary()
print(Int(binary))
// 在用浮点数初始化一个新的整数类型的时候,数值会被截断。也就是说 4.75 会变成 4 , -3.9 会变为 -3 。
// # 类型别名
typealias Student = Int
let tom = Student(8)
let jerry = Int(3)
// # 布尔值
// # 元组
// 是值类型
// 元组可以合起来使用
let coupleOne = ("James", "Marry")
print(coupleOne)
print(coupleOne.0)
// 也可以分开使用,又叫拆分,是单独提取元组元素时用
let (husband, wife) = ("Bob", "Lily")
print("The husband is \(husband)")
// trick: 拆分过程中不需要的用_代替
let (anotherHusband, _) = ("Kevin", "Sophia")
print(anotherHusband)
// 调整内部名,也可以就用默认.0, .1等访问。注意这并非是拆分了元组,不能直接用新名字。另外可以看到,coupleFour的类型为(fourthHusband: String, fourthWife: String)而不是(String, String),有本质区别
let coupleFour = (fourthHusband: "King", fourthWife: "Darling")
print(coupleFour.1)
print(coupleFour.fourthHusband)
// # 可选项
// trick: String转换为Int的初始化器,返回一个Int?
let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
var sir: String? // var类型可选被自动设值为nil
let shemale: String? // let类型可选不会被隐式初始化为nil
shemale = "Jack" // 此时被初始化,此后不能再改变其值
var lady: String? = "Sophia"
// 在类型中,也可以得到体现
class Dog {
var name: String? // 若为let,会报错并提示init未对其初始化
var color: String
init(ofColor color: String) {
self.color = color
}
}
// 用if判断然后强制展开,好处是不用多令一个常量并且保证安全
if convertedNumber != nil {
print("convertedNumber contains some intrgar value and it's \(convertedNumber!)")
}
// 可选项绑定,可用于if和while语句,好处是可以多一个变量来使用可选包含的量并且安全。注意,控制流里定义的变量在之后消失 while let???
if let actualNumber = Int(possibleNumber) {
print("\'\(possibleNumber)\' has an integer value of \(actualNumber)")
} else {
print("\'\(possibleNumber)\' could not be converted to an integer")
}
// trick: 在同一个if语句中包含多个可选项绑定和布尔运算,用逗号隔开,相当于“与”运算。
if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber, secondNumber < 100 {
print("\(firstNumber) < \(secondNumber) < 100")
}
// 隐式展开可选项:既不用写所在类的初始化器,又不用麻烦地每次强制展开。也可以用if判断或者用可选项绑定
var assumedString: String!
assumedString = "OK"
assumedString = nil
// trick: 不要在一个变量将来会变为 nil 的情况下使用隐式展开可选项。这样有些危险,不如用普通可选项了。
// ??:合并空值运算符
var flag: Bool?
var shitIsGood = flag ?? false
print(shitIsGood)
// # 错误处理
// 函数声明过程加上throws关键字
func makeASandwich() throws {
}
// 调用函数时,在表达式前置try关键字。do语句创建容器范围,可让错误传递到catch分句
/*
do {
try makeASandwich()
// 如果没有错误,则调用
eatASandwich()
} catch Error.OutOfCleanDishes {
washDishes()
} catch Error.MissingIngredients(let ingredients) {
buyGroceries(ingredients)
}
*/
// # 断言和先决条件
// 断言:一个从宏观角度检查程序的全局函数,并且只在调试阶段触发
let age = 3
assert(age >= 0, "A person's age cannot be less than zero")
// 直接断言
if age >= 0 {
print("You are human now")
} else {
assertionFailure("A person's age cannot be less than zero")
}
// 先决条件,差不多,具体差异???
precondition(age >= 0, "A person's age cannot be less than zero")
// fatalError(_:file:line:)也差不多,只是不用执行检查罢了