let常量值
let 表示定义好的常量值,并不一定在编译期确定但是的确只能被初始化一次。
let lfkdsk = 1000 // 直接初始化
let lfkdsk : Int // 没有直接初始化要提供类型推倒
lfkdsk = 100
let lfkdsk = 100 + String(1000) // 类型转化要使用显示转换
let apple = 1000
let lfkdsk = "lfkdsk have \(apple) apples" // 类比Ruby的${}
字典和元组
var shoppingList = ["fuck ","you"]
var occupations = ["S":"M","F","Y"]
occupations["F"] = xxx
// 这些都很好理解
// 创建空数组合字典 可以写出类型
let emptyArray = [String]() // 但是初始化之后就不能再修改了
let emptyDictionary = [String: Float]()
类型可以显示推断的话用:
shoppingList = []
occupations = [:]
条件控制
使用if和switch来进行条件操作,使用for-in、for、while和repeat-while来进行循环。包裹条件和循环变量括号可以省略,但是语句体的大括号是必须的。
后加?表示可选变量
let nickName: String? = nil
let fullName: String = "John Appleseed"
// 另一种提供默认值的方式
let informalGreeting = "Hi \(nickName ?? fullName)”
Swich语句支持多种类型和表达式,无需break但是不可缺少default:
let vegetable = "red pepper"
switch vegetable {
case "celery":
print("Add some raisins and make ants on a log.")
case "cucumber", "watercress":
print("That would make a good tea sandwich.")
case let x where x.hasSuffix("pepper"):
print("Is it a spicy \(x)?")
default:
print("Everything tastes good in soup.")
}
for-in语句,可设定key-value值的样子:
let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]
var largest = 0
for (kind, numbers) in interestingNumbers {
for number in numbers {
if number > largest {
largest = number
}
}
}
while语句:
var n = 2
while n < 100 {
n = n * 2
}
print(n)
var m = 2
repeat {
m = m * 2
} while m < 100
print(m)
// 你可以在循环中使用..<来表示范围。
var total = 0
for i in 0..<4 { // 0...<4包含上界
total += i
}
print(total)
函数和闭包
func greet(name: String, day: String) -> String {
return "Hello \(name), today is \(day)."
}
greet(name:"Bob", day: "Tuesday")
如代码所示,使用参数调用函数,使用->设定返回值(总的来说语法很类似)。
func calculateStatistics(scores: [Int]) -> (min: Int, max: Int, sum: Int) {
var min = scores[0]
var max = scores[0]
var sum = 0
for score in scores {
if score > max {
max = score
} else if score < min {
min = score
}
sum += score
}
return (min, max, sum)
}
let statistics = calculateStatistics(scores:[5, 3, 100, 3, 9])
print(statistics.sum)
print(statistics.2)
返回多个返回值。
func sumOf(numbers: Int...) -> Int {
var sum = 0
for number in numbers {
sum += number
}
return sum
}
sumOf()
sumOf(numbers: 42, 597, 12)
可变参数,这个和很多语言都很类似。
可定义函数内函数,作用域包含外界,所以也可以传递函数:
func makeIncrementer() -> ((Int) -> Int) {
func addOne(number: Int) -> Int {
return 1 + number
}
return addOne
}
var increment = makeIncrementer()
increment(7)
func hasAnyMatches(list: [Int], condition: (Int) -> Bool) -> Bool {
for item in list {
if condition(item) {
return true
}
}
return false
}
func lessThanTen(number: Int) -> Bool {
return number < 10
}
var numbers = [20, 19, 7, 12]
hasAnyMatches(list: numbers, condition: lessThanTen)
函数实际上是一种特殊的闭包:它是一段能之后被调取的代码。闭包中的代码能访问闭包所建作用域中能得到的变量和函数,即使闭包是在一个不同的作用域被执行的 - 你已经在嵌套函数例子中所看到。你可以使用{}来创建一个匿名闭包。使用in将参数和返回值类型声明与闭包函数体进行分离。
numbers.map({
(number: Int) -> Int in // 匿名闭包 使用 in 区分
let result = 3 * number
return result
})
var numbers = [20, 19, 7, 12]
numbers.map({
(number :Int) -> (Bool) in
let result = number % 2 != 0;
return result;
})
numbers.sort{ $0 > $1}
print(numbers)
类和对象
class Shape {
var numberOfSides = 0
func simpleDescription() -> String {
return "A shape with \(numberOfSides) sides."
}
}
var shape = Shape()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()
类中的init和deinit函数是构造函数和析构函数。
子类在类名后添加父类的名称,函数重载需要加override标签。
class EquilateralTriangle: NamedShape {
var sideLength: Double = 0.0
init(sideLength: Double, name: String) {
self.sideLength = sideLength
super.init(name: name)
numberOfSides = 3
}
var perimeter: Double {
get {
return 3.0 * sideLength
}
set {
sideLength = newValue / 3
}
}
override func simpleDescription() -> String {
return "An equilateral triagle with sides of length \(sideLength)."
}
}
var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
print(triangle.perimeter)
triangle.perimeter = 9.9
print(triangle.sideLength)
构造器执行了三步:
- 设置子类声明的属性值
- 调用父类的构造器
- 改变父类的属性值,其他的工作如调用方法,
getters和setters也可以在这个阶段完成。
class TriangleAndSquare {
var triangle: EquilateralTriangle {
willSet {
square.sideLength = newValue.sideLength
}
}
var square: Square {
willSet {
triangle.sideLength = newValue.sideLength
}
}
init(size: Double, name: String) {
square = Square(sideLength: size, name: name)
triangle = EquilateralTriangle(sideLength: size, name: name)
}
}
var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")
print(triangleAndSquare.square.sideLength)
print(triangleAndSquare.triangle.sideLength)
triangleAndSquare.square = Square(sideLength: 50, name: "larger square")
print(triangleAndSquare.triangle.sideLength)
处理变量的可选值时,你可以在操作(比如方法、属性和子脚本)之前加?。如果?之前的值是nil,?后面的东西都会被忽略,并且整个表达式返回nil。否则,?之后的东西都会被运行。在这两种情况下,整个表达式的值也是一个可选值。
let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength
枚举和结构体
enum Rank: Int {
case Ace = 1
case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
case Jack, Queen, King
func simpleDescription() -> String {
switch self {
case .Ace:
return "ace"
case .Jack:
return "jack"
case .Queen:
return "queen"
case .King:
return "king"
default:
return String(self.rawValue)
}
}
}
let ace = Rank.Ace
let aceRawValue = ace.rawValue
枚举可以包含方法。
struct的使用:
struct Card {
var rank: Rank
var suit: Suit
func simpleDescription() -> String {
return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
}
}
let threeOfSpades = Card(rank: .Three, suit: .Spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()
结构体和类的区别是,结构体是传值,类是传引用。
enum ServerResponse {
case Result(String, String)
case Failure(String)
}
// 实例和原始值
let success = ServerResponse.Result("6:00 am", "8:09 pm")
let failure = ServerResponse.Failure("Out of cheese.")
switch success {
case let .Result(sunrise, sunset):
let serverResponse = "Sunrise is at \(sunrise) and sunset is at \(sunset)."
case let .Failure(message):
print("Failure... \(message)")
}
协议和扩展
使用protocol来声明一个协议,就是interface,protocol这种命名真是奇怪。
使用mutating来标记Struct中改变内容的值,使用extension拓展一个类的内容。
protocol ExampleProtocol {
var simpleDescription: String { get }
mutating func adjust()
}
class SimpleClass: ExampleProtocol {
var simpleDescription: String = "A very simple class."
var anotherProperty: Int = 69105
func adjust() {
simpleDescription += " Now 100% adjusted."
}
}
extension Int: ExampleProtocol {
var simpleDescription: String {
return "The number \(self)"
}
mutating func adjust() {
self += 42
}
}
print(7.simpleDescription)
错误处理
嗯,首先有Error这个Interface来代表错误信息。
函数后标记throw表示可以抛出错误。
错误处理:
func sendToPrinter(printerName: String) throws -> String {
if printerName == "Never Has Toner" {
throw PrinterError.NoToner
}
return "Job sent"
}
do {
let printerResponse = try sendToPrinter("Bi Sheng")
print(printerResponse)
} catch {
print(error)
}
let printerSuccess = try? sendToPrinter("Mergenthaler")
let printerFailure = try? sendToPrinter("Never Has Toner")
defer绑定函数结尾,写到这,我觉得swift越来越像golang了。
var fridgeIsOpen = false
let fridgeContent = ["milk", "eggs", "leftovers"]
func fridgeContains(_ food: String) -> Bool {
fridgeIsOpen = true
defer {
fridgeIsOpen = false
}
let result = fridgeContent.contains(food)
return result
}
fridgeContains("banana")
print(fridgeIsOpen)
泛型
func repeatItem<Item>(repeating item: Item, numberOfTimes: Int) -> [Item] {
var result = [Item]()
for _ in 0..<numberOfTimes {
result.append(item)
}
return result
}
repeatItem(repeating: "knock", numberOfTimes:4)
返回一个泛型数组,使用where子句实现泛型的特化。