基本数据类型
//变量和常量
var myVaiable = 42
myVariable = 50
let myConstant = 42
let implicitInteger = 70
let implicitDouble = 70.0
let explicitDouble: Double = 70 //可在定义时制定类型,不指定时根据值来推断类型
let label = "The width is "
let width = 94
let widthLabel = label + String(width) //不能隐身转换类型
//使用\()可以在字符串中做运算操作
let apples = 3
let oranges = 5
let appleSummary = "I have \(apples) apples."
let fruitSummary = "I have \(apples + oranges) pieces of fruit.
//数组和字典
var shoppingList = ["catfish", "water", "tulips", "blue paint"]
shoppingList[1] = "bottle of water"
var occupations = [
"Malcolm": "Captain",
"Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations"
let emptyArray = [String]()
let emptyDictionary = [String: Float]()”
//如果知道数组或字典里元素的类型,则可以用[]或[:]给对应数组或字典赋空值
shoppingList = []
occupations = [:]
控制流
let individualScores = [75, 43, 103, 87, 12]
var teamScore = 0
for score in individualScores { //循环条件可以不用括号
if score > 50 {//这里必须用花括号,判断条件必须为布尔值
teamScore += 3
} else {
teamScore += 1
}
}
print(teamScore)
var optionalString: String? = "Hello"
print(optionalString == nil)
var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
greeting = "Hello, \(name)"
}
let nickName: String? = nil
let fullName: String = "John Appleseed"
let informalGreeting = "Hi \(nickName ?? fullName)
let vegetable = "red pepper"
switch vegetable {
case "celery":
print("Add some raisins and make ants on a log.")//不需要break,因为有符合条件的就不执行后面的
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.")
}
//遍历字典、数组
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
}
}
}
print(largest)
//while循环
var n = 2
while n < 100 {
n *= 2
}
print(n)
var m = 2
repeat {
m *= 2
} while m < 100
print(m)
//..<不包括右边的值 ...包括右边的值
var total = 0
for i in 0..<4 {
total += i
}
print(total)
函数和闭包
func greet(person: String, day: String) -> String {
return "Hello \(person), today is \(day)."
}
greet(person: "Bob", day: "Tuesday")
func greet(_ person: String, on day: String) -> String {
return "Hello \(person), today is \(day)."
}
greet("John", on: "Wednesday")
//元组
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 returnFifteen() -> Int {
var y = 10
func add() {
y += 5
}
add()
return y
}
returnFifteen()
//返回值为函数的函数
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)
//函数是一种特殊的闭包
numbers.map({ (number: Int) -> Int in
let result = 3 * number
return result
})
//闭包类型已知,可以省略类型
let mappedNumbers = numbers.map({ number in 3 * number })
print(mappedNumbers)
//可以用角标代替参数名,当闭包为函数的最后一个参数时,可写在括号后,当函数的参数只有一个闭包时,可省略括号
let sortedNumbers = numbers.sorted { $0 > $1 }
print(sortedNumbers)
对象和类
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()析构函数. 属性必须在声明时候初始化,或者在构造器中初始化
class NamedShape {
var numberOfSides: Int = 0
var name: String
init(name: String) {
self.name = name
}
func simpleDescription() -> String {
return "A shape with \(numberOfSides) sides."
}
}
//子类
class Square: NamedShape {
var sideLength: Double
init(sideLength: Double, name: String) {
self.sideLength = sideLength
super.init(name: name)
numberOfSides = 4
}
func area() -> Double {
return sideLength * sideLength
}
override func simpleDescription() -> String {
return "A square with sides of length \(sideLength)."
}
}
let test = Square(sideLength: 5.2, name: "my test square")
test.area()
test.simpleDescription()
//getter & setter
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.0
}
}
override func simpleDescription() -> String {
return "An equilateral triangle with sides of length \(sideLength)."
}
}
var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
print(triangle.perimeter)
triangle.perimeter = 9.9
print(triangle.sideLength)
//willSet 保证正方形和三角形的变长相等(init方法之外的属性 )
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)
枚举和结构体
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
One of the most important differences between structures and classes is that structures are always copied when they are passed around in your code, but classes are passed by reference.
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()
协议和扩展
protocol ExampleProtocol {
var simpleDescription: String { get }
mutating func adjust()//如果将ExampleProtocol中修饰方法的mutating去掉,编译器会报错说没有实现protocol。如果将struct中的mutating去掉,则会报错不能改变结构体的成员。
}
//Classes, enumerations, and structs can all adopt protocols.
class SimpleClass: ExampleProtocol {
var simpleDescription: String = "A very simple class."
var anotherProperty: Int = 69105
func adjust() {// 在 class 中实现带有mutating方法的接口时,不用mutating进行修饰。因为对于class来说,类的成员变量和方法都是透明的,所以不必使用 mutating 来进行修饰
simpleDescription += " Now 100% adjusted."
}
}
var a = SimpleClass()
a.adjust()
let aDescription = a.simpleDescription
struct SimpleStructure: ExampleProtocol {
var simpleDescription: String = "A simple structure"
mutating func adjust() {//使用 mutating 关键字修饰方法是为了能在该方法中修改 struct 或是 enum 的变量
simpleDescription += " (adjusted)"
}
}
var b = SimpleStructure()
b.adjust()
let bDescription = b.simpleDescription
//在enum中实现协议ExampleProtocol
enum SimpleEnum: ExampleProtocol {
case First, Second, Third
var simpleDescription: String {
get {
switch self {
case .First:
return "first"
case .Second:
return "second"
case .Third:
return "third"
}
}
set {
simpleDescription = newValue
}
}
mutating func adjust() {
}
}
//扩展
extension Int: ExampleProtocol {
var simpleDescription: String {
return "The number \(self)"
}
mutating func adjust() {//Int是结构体
self += 42
}
}
print(7.simpleDescription)
//这种类型为协议的常量,只能使用协议里定义的属性和方法
let protocolValue: ExampleProtocol = a
//Error协议用于错误处理
enum PrinterError: Error {
case outOfPaper
case noToner
case onFire
}
//throws标示函数能够抛出异常
func send(job: Int, toPrinter printerName: String) throws -> String {
if printerName == "Never Has Toner" {
throw PrinterError.noToner
}
return "Job sent"
}
do {
let printerResponse = try send(job: 1040, toPrinter: "Bi Sheng")
print(printerResponse)
} catch {
print(error)
}
//还可以捕获多种类型的异常
do {
let printerResponse = try send(job: 1440, toPrinter: "Gutenberg")
print(printerResponse)
} catch PrinterError.onFire {
print("I'll just put this over here, with the rest of the fire.")
} catch let printerError as PrinterError {
print("Printer error: \(printerError).")
} catch {
print(error)
}
//try? 会试图执行一个可能会抛出异常的操作。如果成功抛出异常,执行的结果就会包裹在可选值(optional)里;如果抛出异常失败(比如:已经在处理 error),那么执行的结果就是 nil ,而且没有 error。
let printerSuccess = try? send(job: 1884, toPrinter: "Mergenthaler")
let printerFailure = try? send(job: 1885, toPrinter: "Never Has Toner")
//defer关键字(推迟执行)
// 伪代码,我们将closeFile(file)放在defer代码块里,这样即使ioStatus为error,在执行return前会先执行defer里的代码,这样就保证了不管发生什么,最后都会将文件关闭。需要注意的是, 虽然说defer的内容会在return之前执行, 但是如果defer定义在return之后, 那么还是不会执行defter的内容, 也就是说, defer关键字必须比return早出现。
func writeSomething() {
let file = OpenFile()
defer {
closeFile(file)
}
let ioStatus = fetchIOStatus()
guard ioStatus != "error" else {
return
}
file.write()
}
泛型
func makeArray<Item>(repeating item: Item, numberOfTimes: Int) -> [Item] {
var result = [Item]()
for _ in 0..<numberOfTimes {//如果你不需要知道区间内每一项的值,你可以使用下划线(_)替代变量名来忽略对值的访问
result.append(item)
}
return result
}
makeArray(repeating: "knock", numberOfTimes:4)
//You can make generic forms of functions and methods, as well as classes, enumerations, and structures.