Swift 5.1 極簡參考手冊

本文由 漫慢忙 翻譯自 raywenderlich 教程 Swift 5.1 Cheat Sheet and Quick Reference ,請參考原文閱讀json

聲明常量和變量

• 使用 let 關鍵字聲明一個常量swift

let double: Double = 2.0
// double = 3.0 // 錯誤:不能給常量從新賦值
let inferredDouble = 2.0 // 推斷爲一個 Double 類型
複製代碼

• 使用 var 關鍵字聲明一個變量bash

var mutableInt: Int = 1
mutableInt = 2 // OK: 能夠給一個變量從新賦值
複製代碼

數值類型轉換

let integerValue = 8
let doubleValue = 8.0
//let sum = integerValue + double // 錯誤:類型不匹配
複製代碼

• 使用顯式的方法來防止隱藏的轉換錯誤並有助於明確類型轉換意圖閉包

let sum = Double(integerValue) + double // OK: 兩個值有相同類型
複製代碼

字符串

• 使用字符串字面量來初始化一個常量或變量app

let helloWorld = "Hello, World!"
複製代碼

• 使用多行字符串字面量來跨越多行ide

let helloWorldProgram = """ A "Hello, World!" program generally is a computer program that outputs or displays the message "Hello, World!" """
複製代碼

• 空字符串函數

let emptyString = "" // 使用字符串字面量
let anotherEmptyString = String() // 初始化語法
複製代碼

• 修改字符串測試

var mutableString = "Swift"
mutableString += " is awesome!"
複製代碼

• 字符串插值ui

print("The value is \(double)") // 插入一個 Double 值
print("This is my opinion: \(mutableString)") // 插入一個字符串
複製代碼

元組

• 將多個值組合爲一個複合值spa

let httpError = (503, "Server Error")
複製代碼

• 分解元組的內容

let (code, reason) = httpError

// 另外一種分解方式
let codeByIndex = httpError.0
let reasonByIndex = httpError.1
複製代碼

• 使用 _ 來忽略元組的某些部分

let (_, justTheReason) = httpError
複製代碼

可選項

• catchphrase 能夠包含 String 或 nil

var catchphrase: String? // 由編譯器自動設置爲nil
catchphrase = "Hey, what's up, everybody?"
複製代碼

• 強制解包操做符 (!)

// 若是 catchphrase 不是nil,count1 包含 catchphrase 的計數值;
// 不然程序崩潰
let count1: Int = catchphrase!.count
複製代碼

• 可選綁定

// 若是 catchphrase?.count 返回的可選 Int 包含一個值,
// 則將一個稱爲 count 的新常量設置爲可選中包含的值
if let count = catchphrase?.count {
  print(count)
}
複製代碼

• 合併操做符(??)

// 若是 catchphrase 不是 nil,count2 包含 catchphrase 的 count 值; 不然爲 0
let count2: Int = catchphrase?.count ?? 0
複製代碼

• 鏈式操做符(?)

// 若是 catchphrase 不是nil,count3 包含 catchphrase 的 count 值; 不然爲 nil
let count3: Int? = catchphrase?.count
複製代碼

• 隱式展開的可選值

let forcedCatchphrase: String! = "Hey, what's up, everybody?"
let implicitCatchphrase = forcedCatchphrase // 無需使用感嘆號
複製代碼

集合類型:Array

let immutableArray: [String] = ["Alice", "Bob"]
// mutableArray 的類型爲 [String]
var mutableArray = ["Eve", "Frank"]
複製代碼

• 測試包含關係

let isEveThere = immutableArray.contains("Eve")
let name: String = immutableArray[0] // 經過索引訪問
複製代碼

• 在列表中修改項目

// 若是索引越界,則崩潰
mutableArray[1] = "Bart"
// immutableArray[1] = "Bart" // 錯誤:不能修改
mutableArray.append("Ellen") // 添加項目
mutableArray.insert("Gemma", at: 1) // 在指定索引處添加項目

// 不能從新賦值一個常量集合或修改它的內容
// 能夠從新賦值一個可變集合和修改它的w內容
mutableArray = ["Ilary", "David"]
mutableArray[0] = "John"
複製代碼

• 經過索引來刪除

let removedPerson = mutableArray.remove(at: 1)
複製代碼

集合類型: Dictionary

let immutableDict: [String: String] = ["name": "Kirk", "rank": "captain"]
// mutableDict 的類型爲 [String: String]
var mutableDict = ["name": "Picard", "rank": "captain"]
複製代碼

• 經過 key 來訪問,若是不存在對應的 key,則返回 nil

let name2: String? = immutableDict["name"]
複製代碼

• 更新 key 對應的 value

mutableDict["name"] = "Janeway"
複製代碼

• 添加新的 key-value

mutableDict["ship"] = "Voyager"
複製代碼

• 經過 key 來刪除項目,若是 key 不存在,則返回 nil

let rankWasRemoved: String? = mutableDict.removeValue(forKey: "rank")
複製代碼

集合類型: Set

• Set 會忽略重複項,因此 immutableSet 只有 2 項:"chocolate" 和 "vanilla"

let immutableSet: Set = ["chocolate", "vanilla", "chocolate"]
var mutableSet: Set = ["butterscotch", "strawberry"]
複製代碼

• 測試包含關係

immutableSet.contains("chocolate")
複製代碼

• 添加項目

mutableSet.insert("green tea")
複製代碼

• 移除項目,若是沒有找到項目,則返回 nil

let flavorWasRemoved: String? = mutableSet.remove("strawberry")
複製代碼

控制流:循環

• 遍歷一個列表或集合

//for item in listOrSet {
//    print(item)
//}
複製代碼

• 遍歷字典

//for (key, value) in dictionary {
//    print("\(key) = \(value)")
//}
複製代碼

• 遍歷範圍

// 閉區間操做符(...)
for i in 0...10 {
  print(i) // 0 to 10
}
// 半開區間操做符(..<)
for i in 0..<10 {
  print(i) // 0 to 9
}
複製代碼

• while

var x = 0
while x < 10 {
  x += 1
  print(x)
}
複製代碼

• repeat-while

repeat {
  x -= 1
  print(x)
} while(x > 0)
複製代碼

控制流:條件語句

• 使用 if 來選擇不一樣路徑

let number = 88
if (number <= 10) {
  // 若是 number <= 10, 則執行這裏
} else if (number > 10 && number < 100) {
  // 若是 number > 10 && number < 100, 則執行這裏
} else {
  // 不然執行這裏
}
複製代碼

• 三元操做符

// if-else條件的簡寫
let height = 100
let isTall = height > 200 ? true : false
複製代碼

• 若是不知足一個或多個條件,請使用 guard 將程序控制權轉移出一個範圍

for n in 1...30 {
  guard n % 2 == 0 else {
    continue
  }
  print("\(n) is even")
}
複製代碼

• 使用 switch 來選擇不一樣路徑

let year = 2012
switch year {
case 2003, 2004:
  // 若是 year 是 2003 或者 2004,則執行這個語句
  print("Panther or Tiger")
case 2010:
  // 若是 year 的值是 2010,則執行這個語句
  print("Lion")
case 2012...2015:
  // 若是 year 在 2012-2015 範圍內(包含邊界值),則執行這個語句
  print("Mountain Lion through El Captain")
default: // 每一個 switch 語句必須涵蓋全部狀況
  print("Not already classified")
}
複製代碼

函數

• 返回 Void 的函數

func sayHello() {
  print("Hello")
}
複製代碼

• 帶參數的函數

func sayHello(name: String) {
  print("Hello \(name)!")
}
複製代碼

• 帶默認參數值的函數

//func sayHello(name: String = "Lorenzo") {
//  print("Hello \(name)!")
//}
複製代碼

• 混合默認值的參數和常規參數的函數

//func sayHello(name: String = "Lorenzo", age: Int) {
//  print("\(name) is \(age) years old!")
//}
//
//sayHello(age: 35) // 只使用非默認值參數調用
複製代碼

• 帶參數和返回值的函數

func add(x: Int, y: Int) -> Int {
  return x + y
}
let value = add(x: 8, y: 10)
複製代碼

• 若是函數只有一個表達式,則能夠省略 return

func multiply(x: Int, y: Int) -> Int {
  x + y
}
複製代碼

• 指定參數的 label

//func add(x xVal: Int, y yVal: Int) -> Int {
//  return xVal + yVal
//}
複製代碼

• 省略一些參數的參數 label

//func add(_ x: Int, y: Int) -> Int {
//    return x + y
//}
//let value = add(8, y: 10)
複製代碼

• 接受函數做爲參數的函數

func doMath(operation: (Int, Int) -> Int, a: Int, b: Int) -> Int {
  return operation(a, b)
}
複製代碼

閉包

let adder: (Int, Int) -> Int = { (x, y) in x + y }
複製代碼

• 帶有速記參數名的閉包

let square: (Int) -> Int = { $0 * $0 }
複製代碼

• 將一個閉包傳遞給函數

let addWithClosure = doMath(operation: adder, a: 2, b: 3)
複製代碼

枚舉

enum Taste {
  case sweet, sour, salty, bitter, umami
}
let vinegarTaste = Taste.sour
複製代碼

• 迭代枚舉

enum Food: CaseIterable {
  case pasta, pizza, hamburger
}

for food in Food.allCases {
  print(food)
}
複製代碼

• 帶有 String 原始值的枚舉

enum Currency: String {
  case euro = "EUR"
  case dollar = "USD"
  case pound = "GBP"
}
複製代碼

• 打印原始值

let euroSymbol = Currency.euro.rawValue
print("The currency symbol for Euro is \(euroSymbol)")
複製代碼

• 帶有關聯值的枚舉

enum Content {
  case empty
  case text(String)
  case number(Int)
}
複製代碼

• 使用 switch 語句來匹配枚舉值

let content = Content.text("Hello")
switch content {
case .empty:
  print("Value is empty")
case .text(let value): // 提取 String 值
  print("Value is \(value)")
case .number(_): // 忽略 Int 值
  print("Value is a number")
}
複製代碼

結構體

struct User {
  var name: String
  var age: Int = 40
}
複製代碼

• 結構體自動建立一個逐一構造器,該構造器接收與全部屬性匹配的參數

let john = User(name: "John", age: 35)
複製代碼

• 若是屬性有初始值,逐一構造器會將其做爲默認參數值

let dave = User(name: "Dave")
複製代碼

• 訪問屬性

print("\(john.name) is \(john.age) years old")
複製代碼

class Person {
  let name: String
  // 類構造器
  init(name: String) {
    self.name = name
  }
  
  // 使用 deinit 來執行對象資源清理操做
  deinit {
    print("Perform the deinitialization")
  }
  
  var numberOfLaughs: Int = 0
  func laugh() {
    numberOfLaughs += 1
  }
  
  // 定義一個計算屬性
  var isHappy: Bool {
    return numberOfLaughs > 0
  }
}

let david = Person(name: "David")
david.laugh()
let happy = david.isHappy
複製代碼

• 繼承

class Student: Person {
  var numberOfExams: Int = 0
  
  // 重寫 isHappy 計算屬性,以提供額外邏輯
  override var isHappy: Bool {
    numberOfLaughs > 0 && numberOfExams > 2
  }
}

let ray = Student(name: "Ray")
ray.numberOfExams = 4
ray.laugh()
//let happy = ray.isHappy
複製代碼

• 用 final 來標記 Child,以阻止其被繼承

final class Child: Person { }
複製代碼

• 指定構造器和便捷構造器

// 一個類須要至少一個指定構造器
// 同時能夠有一個或多個便捷構造器
class ModeOfTransportation {
  let name: String
  // 定義一個指定構造器
  // 其攜帶一個名爲 name 的參數
  init(name: String) {
    self.name = name
  }
  
  // 定義一個便捷構造器
  // 沒有攜帶參數
  convenience init() {
    // 委託給內部指定構造器
    self.init(name: "Not classified")
  }
}

class Vehicle: ModeOfTransportation {
  let wheels: Int
  // 定義一個指定構造器
  // 帶有兩個參數
  init(name: String, wheels: Int) {
    self.wheels = wheels
    // 委託給父類指定構造器
    super.init(name: name)
  }
  
  // 重寫父類便捷構造器
  override convenience init(name: String) {
    // 委託給內部指定構造器
    self.init(name: name, wheels: 4)
  }
}
複製代碼

擴展

• 擴展能夠給已存在的類、結構體、枚舉或協議類型添加新的功能

extension String {
  // 擴展 String 類型來計算一個 String 實例是真仍是假
  var boolValue: Bool {
    if self == "1" {
      return true
    }
    return false
  }
}

let isTrue = "0".boolValue
複製代碼

錯誤處理

• 表示一個錯誤

enum BeverageMachineError: Error {
  case invalidSelection
  case insufficientFunds
  case outOfStock
}

func selectBeverage(_ selection: Int) throws -> String {
  // Some logic here
  return "Waiting for beverage..."
}
複製代碼

• 若是在 do 代碼塊中拋出一個異常,它會與catch子句匹配,以肯定其中哪個能夠處理錯誤

let message: String
do {
  message = try selectBeverage(20)
} catch BeverageMachineError.invalidSelection {
  print("Invalid selection")
} catch BeverageMachineError.insufficientFunds {
  print("Insufficient funds")
} catch BeverageMachineError.outOfStock {
  print("Out of stock")
} catch {
  print("Generic error")
}
複製代碼

• 若是在 try? 語句中拋出一個錯誤,則表達式的值爲 nil

let nillableMessage = try? selectBeverage(10)
複製代碼

• 若是拋出一個異常,則會致使運行時錯誤;不然獲取返回值

let throwableMessage = try! selectBeverage(10)
複製代碼

訪問控制

• 一個模塊(framework 或 application)是一個獨立的代碼分發單元,能夠在其它模塊中經過 import 關鍵字來導入

public class AccessLevelsShowcase { // 能夠從其它模塊中訪問類
  public var somePublicProperty = 0 // 能夠從其它模塊中訪問該屬性
  var someInternalProperty = 0 // 能夠在包含該類的塊中訪問該屬性
  fileprivate func someFilePrivateMethod() {} // 能夠從定義該類的源文件中訪問該屬性
  private func somePrivateMethod() {} // 能夠在該類的代碼塊中訪問該屬性
}
複製代碼

協議

• Codable 和 Decodable/Encodable 兩個協議的組合是同樣的

import Foundation
struct UserInfo: Codable {
  let username: String
  let loginCount: Int
}
複製代碼

• 實現 CustomStringConvertible 協議來提供將實例轉換化字符串時的描述信息

extension UserInfo: CustomStringConvertible {
  var description: String {
    return "\(username) has tried to login \(loginCount) time(s)"
  }
}
複製代碼

• 定義一個表達 JSON 的多行字符串

let json = """ { "username": "David", "loginCount": 2 } """
複製代碼

• 使用 JSONDecoder 來序列化一個 JSON

let decoder = JSONDecoder()
複製代碼

• 將字符串轉化爲 UserInfo 實例

let data = json.data(using: .utf8)!
let userInfo = try! decoder.decode(UserInfo.self, from: data)
print(userInfo)
複製代碼

• 使用 Encodable 來序列化一個結構體

let encoder = JSONEncoder()
let userInfoData = try! encoder.encode(userInfo)
複製代碼

• 將 UserInfo 實例轉換爲字符串表示

let jsonString = String(data: userInfoData, encoding: .utf8)!
print(jsonString)
複製代碼

更多好文,請關注公衆號 "知識小集" (ID: zsxjtip)

相關文章
相關標籤/搜索