基本數(shù)據(jù)類型
//變量和常量
var myVaiable = 42
myVariable = 50
let myConstant = 42
let implicitInteger = 70
let implicitDouble = 70.0
let explicitDouble: Double = 70 //可在定義時(shí)制定類型,不指定時(shí)根據(jù)值來推斷類型
let label = "The width is "
let width = 94
let widthLabel = label + String(width) //不能隱身轉(zhuǎn)換類型
//使用\()可以在字符串中做運(yùn)算操作
let apples = 3
let oranges = 5
let appleSummary = "I have \(apples) apples."
let fruitSummary = "I have \(apples + oranges) pieces of fruit.
//數(shù)組和字典
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]()”
//如果知道數(shù)組或字典里元素的類型,則可以用[]或[:]給對應(yīng)數(shù)組或字典賦空值
shoppingList = []
occupations = [:]
控制流
let individualScores = [75, 43, 103, 87, 12]
var teamScore = 0
for score in individualScores { //循環(huán)條件可以不用括號
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,因?yàn)橛蟹蠗l件的就不執(zhí)行后面的
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.")
}
//遍歷字典、數(shù)組
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循環(huán)
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)
函數(shù)和閉包
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)//也可以用下標(biāo)訪問
//可變數(shù)量參數(shù)的函數(shù)
func sumOf(numbers: Int...) -> Int {
var sum = 0
for number in numbers {
sum += number
}
return sum
}
sumOf()
sumOf(numbers: 42, 597, 12)
//嵌套函數(shù)
func returnFifteen() -> Int {
var y = 10
func add() {
y += 5
}
add()
return y
}
returnFifteen()
//返回值為函數(shù)的函數(shù)
func makeIncrementer() -> ((Int) -> Int) {
func addOne(number: Int) -> Int {
return 1 + number
}
return addOne
}
var increment = makeIncrementer()
increment(7)
//參數(shù)為函數(shù)的函數(shù)
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)
//函數(shù)是一種特殊的閉包
numbers.map({ (number: Int) -> Int in
let result = 3 * number
return result
})
//閉包類型已知,可以省略類型
let mappedNumbers = numbers.map({ number in 3 * number })
print(mappedNumbers)
//可以用角標(biāo)代替參數(shù)名,當(dāng)閉包為函數(shù)的最后一個(gè)參數(shù)時(shí),可寫在括號后,當(dāng)函數(shù)的參數(shù)只有一個(gè)閉包時(shí),可省略括號
let sortedNumbers = numbers.sorted { $0 > $1 }
print(sortedNumbers)
對象和類
class Shape {
var numberOfSides = 0
func simpleDescription() -> String {
return "A shape with \(numberOfSides) sides."
}
}
//用類名后加括號聲明一個(gè)對象,使用點(diǎn)語法訪問屬性和方法
var shape = Shape()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()
//init()構(gòu)造函數(shù),deinit()析構(gòu)函數(shù). 屬性必須在聲明時(shí)候初始化,或者在構(gòu)造器中初始化
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)
枚舉和結(jié)構(gòu)體
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()
協(xié)議和擴(kuò)展
protocol ExampleProtocol {
var simpleDescription: String { get }
mutating func adjust()//如果將ExampleProtocol中修飾方法的mutating去掉,編譯器會(huì)報(bào)錯(cuò)說沒有實(shí)現(xiàn)protocol。如果將struct中的mutating去掉,則會(huì)報(bào)錯(cuò)不能改變結(jié)構(gòu)體的成員。
}
//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 中實(shí)現(xiàn)帶有mutating方法的接口時(shí),不用mutating進(jìn)行修飾。因?yàn)閷τ赾lass來說,類的成員變量和方法都是透明的,所以不必使用 mutating 來進(jìn)行修飾
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 關(guān)鍵字修飾方法是為了能在該方法中修改 struct 或是 enum 的變量
simpleDescription += " (adjusted)"
}
}
var b = SimpleStructure()
b.adjust()
let bDescription = b.simpleDescription
//在enum中實(shí)現(xiàn)協(xié)議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() {
}
}
//擴(kuò)展
extension Int: ExampleProtocol {
var simpleDescription: String {
return "The number \(self)"
}
mutating func adjust() {//Int是結(jié)構(gòu)體
self += 42
}
}
print(7.simpleDescription)
//這種類型為協(xié)議的常量,只能使用協(xié)議里定義的屬性和方法
let protocolValue: ExampleProtocol = a
//Error協(xié)議用于錯(cuò)誤處理
enum PrinterError: Error {
case outOfPaper
case noToner
case onFire
}
//throws標(biāo)示函數(shù)能夠拋出異常
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? 會(huì)試圖執(zhí)行一個(gè)可能會(huì)拋出異常的操作。如果成功拋出異常,執(zhí)行的結(jié)果就會(huì)包裹在可選值(optional)里;如果拋出異常失敗(比如:已經(jīng)在處理 error),那么執(zhí)行的結(jié)果就是 nil ,而且沒有 error。
let printerSuccess = try? send(job: 1884, toPrinter: "Mergenthaler")
let printerFailure = try? send(job: 1885, toPrinter: "Never Has Toner")
//defer關(guān)鍵字(推遲執(zhí)行)
// 偽代碼,我們將closeFile(file)放在defer代碼塊里,這樣即使ioStatus為error,在執(zhí)行return前會(huì)先執(zhí)行defer里的代碼,這樣就保證了不管發(fā)生什么,最后都會(huì)將文件關(guān)閉。需要注意的是, 雖然說defer的內(nèi)容會(huì)在return之前執(zhí)行, 但是如果defer定義在return之后, 那么還是不會(huì)執(zhí)行defter的內(nèi)容, 也就是說, defer關(guān)鍵字必須比return早出現(xiàn)。
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 {//如果你不需要知道區(qū)間內(nèi)每一項(xiàng)的值,你可以使用下劃線(_)替代變量名來忽略對值的訪問
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.