Swift 語法概覽(一)

1. 基礎(chǔ)

常量 && 變量

// 常量
let age = 20
// 變量
var weight = 120.4

// 類型標(biāo)識
var welcomeMessage: String
welcomeMessage = "Hello"

// 統(tǒng)一類型
var red, green, blue: Double

整數(shù)

Int:在32位平臺上是Int32,在64位平臺上是Int64
UInt:在32位平臺上是UInt32,在64位平臺上是UInt64
其他整數(shù):Int8,Int16,Int32,Int64
整數(shù)范圍

let minValue = UInt8.min  // minValue is equal to 0, and is of type UInt8
let maxValue = UInt8.max  // maxValue is equal to 255, and is of type UInt8

浮點(diǎn)數(shù)

Float:32位浮點(diǎn)數(shù)
Double:64位浮點(diǎn)數(shù)

類型安全和類型推導(dǎo)

Swift 是類型安全語言,在編譯期間執(zhí)行類型檢查來避免類型錯誤,但這并不意味著定義變量都要指定類型,Swift 提供類型推導(dǎo)機(jī)制,比如:

// Int 類型
var age = 20
// Double 類型
var weight = 120.5
// Double 類型
var height = 170 + 1.5

不同類型之間的數(shù)字運(yùn)算需要做顯式轉(zhuǎn)換,隱式轉(zhuǎn)換不被允許的:

let three = 3
let pointOneFourOneFiveNine = 0.14159
// 不加Double() 轉(zhuǎn)換,報錯
let pi = Double(three) + pointOneFourOneFiveNine

類型別名

typealias AudioSample = UInt16

var maxAmplitudeFound = AudioSample.min

布爾類型

let turnOn = true

if turnOn {
    print("turnOn is true")
} else {
    print("turnOn is false")
}

由于類型安全,Swift 中非布爾類型不能代替布爾類型使用,比如代碼報錯:

// 編譯報錯
if 1 {
  print("1 不能代替 true")
}

元組

元組是一組數(shù)據(jù)的集合,可以是不同的數(shù)據(jù)類型

// 定義一個元組,類型:(Int,  String)
let http404Error = (404, "Not Found")

// 獲取數(shù)據(jù)
let (statusCode, statusMessage) = http404Error
print("The status code is \(statusCode)")
print("The status message is \(statusMessage)")
// 獲取部分?jǐn)?shù)據(jù)
let (justTheStatusCode, _) = http404Error

// 索引訪問
print("The status code is \(http404Error.0)")
print("The status message is \(http404Error.1)")

// 定義時提供別名
let http200Status = (statusCode: 200, description: "OK")
print("The status code is \(http200Status.statusCode)")
print("The status message is \(http200Status.description)")

Optional(可選變量)

optional 修飾的變量代表該變量可能有值,也可能沒值。沒值通過 nil 來表示

不能將非可選變量的值設(shè)置為nil

var serverResponseCode: Int? = 404
serverResponseCode = nil

// 無初始化值默認(rèn)為 nil
var surveyAnswer: String?

Swift 中的 nil 和 OC 中的 nil 不一樣,OC 中的 nil 代表是 空對象指針,用在對象類型上,Swift 的 nil 表示某個變量沒有值,所有類型都可以使用。

可選值的解包

強(qiáng)制解包
當(dāng)確認(rèn)某個變量一定有值的時候,可以使用強(qiáng)制解包符號 !

var convertedNumber: Int? = 404
if convertedNumber != nil {
    print("convertedNumber has an integer value of \(convertedNumber!).")
}

可選綁定
if,while 條件語句可以使用可選綁定來解包

var convertedNumber: Int? = 404
if let actualNumber = convertedNumber {
    print("The convertedNumber has an integer value of \(actualNumber)")
} else {
    print("The convertedNumber has no value")
}

// 多個解包操作,有一個返回 nil 則 if 語句條件判斷失敗
if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber && secondNumber < 100 {
    print("\(firstNumber) < \(secondNumber) < 100")
}

隱式解包
什么玩意?

let possibleString: String? = "An optional string."
// 需要解包使用
let forcedString: String = possibleString! 

let assumedString: String! = "An implicitly unwrapped optional string."
// 不需要解包,根據(jù)類型推導(dǎo),這里會自動強(qiáng)制解包
let implicitString: String = assumedString

// 不自動解包,optionalString 是 optional 類型
let optionalString = assumedString

錯誤處理

func makeASandwich() throws {
    // this function may or may not throw an error
}

do {
    try makeASandwich()
    eatASandwich()
} catch SandwichError.outOfCleanDishes {
    washDishes()
} catch SandwichError.missingIngredients(let ingredients) {
    buyGroceries(ingredients)
}

Assertions and Preconditions

斷言,他們之間的區(qū)別是 Assertions 只在 Debug 環(huán)境下生效,Preconditions 在 Debug 和 Product 環(huán)境下都生效。

let age = -3
assert(age >= 0, "A person's age can't be less than zero.")

precondition(index > 0, "Index must be greater than zero.")

基本運(yùn)算符

賦值運(yùn)算符(=)沒有返回值
默認(rèn)算術(shù)運(yùn)算符不允許值溢出

運(yùn)算符特殊操作:

// 字符串連接
"hello, " + "world"  // equals "hello, world"

// 溢出操作符
let c = a &+ b

// 取余運(yùn)算
a % b
a = (b x some multiplier) + remainder
-9 % 4   // equals -1
-9 = (4 x -2) + -1

// 三元
a != nil ? a! : b 等價于 a ?? b

// 區(qū)間運(yùn)算符
// 閉區(qū)間 a...b
for index in 1...5 {
    print("\(index)")
    //打印 1 2 3 4 5
}
// 半開區(qū)間 a..<b
for index in 1..<5 {
    print("\(index)")
    //打印 1 2 3 4
}
// 單邊區(qū)間 a... or ...a
let name = [1,2,3,4,5]
for name in names[2...] {
    // 區(qū)間[2-4]
    print(name)
}
for name in names[...2] {
    // 區(qū)間[0-2]
    print(name)
}
for name in names[..<2] {
    // 區(qū)間 [0-2)
    print(name)
}
// 當(dāng)變量使用
let range = ...5
range.contains(7)   // false
range.contains(-1)  // true

2. 字符和字符串

初始化操作

var emptyString = ""               // empty string literal
var anotherEmptyString = String()  // initializer syntax

if emptyString.isEmpty {
    print("Nothing to see here")
}

// 可變字符串
var variableString = "Horse"
variableString += " and carriage" // Horse and carriage
// 不可變字符串
let constantString = "Highlander"
constantString += " and another Highlander" // 編譯報錯

字符串字面量

// 單行
let someString = "Some string literal value"

// 多行
let quotation = """
The White Rabbit put on his spectacles.  "Where shall I begin,
please your Majesty?" he asked.

"Begin at the beginning," the King said gravely, "and go on
till you come to the end; then stop."
"""

擴(kuò)展字符

//  \n 不會換行
let str = #"Line 1\nLine 2"#

//  \n 會換行
let str = #"Line 1\#nLine 2"#

字符操作

for character in "Dog!??" {
    print(character)
}
// D o g  ! ??

let exclamationMark: Character = "!"
let catCharacters: [Character] = ["C", "a", "t", "!", "??"]

字符串操作

let string1 = "hello"
let string2 = " there"
var welcome = string1 + string2
// welcome now equals "hello there"

var instruction = "look over"
instruction += string2
// instruction now equals "look over there"

// 字符串插入
let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"

print(#"6 times 7 is \#(6 * 7)."#)
// Prints "6 times 7 is 42."

字符計數(shù)

// 特殊例子
var word = "cafe"
print("the number of characters in \(word) is \(word.count)")
// Prints "the number of characters in cafe is 4"

word += "\u{301}"    // COMBINING ACUTE ACCENT, U+0301

print("the number of characters in \(word) is \(word.count)")
// Prints "the number of characters in café is 4"

字符訪問

let greeting = "Guten Tag!"
greeting[greeting.startIndex]
// G
greeting[greeting.index(before: greeting.endIndex)]
// !
greeting[greeting.index(after: greeting.startIndex)]
// u
let index = greeting.index(greeting.startIndex, offsetBy: 7)
greeting[index]
// a

for index in greeting.indices {
    print("\(greeting[index]) ", terminator: "")
}
// Prints "G u t e n   T a g ! "

插入 && 刪除

var welcome = "hello"
welcome.insert("!", at: welcome.endIndex)
// welcome now equals "hello!"

welcome.insert(contentsOf: " there", at: welcome.index(before: welcome.endIndex))
// welcome now equals "hello there!"

welcome.remove(at: welcome.index(before: welcome.endIndex))
// welcome now equals "hello there"

let range = welcome.index(welcome.endIndex, offsetBy: -6)..<welcome.endIndex
welcome.removeSubrange(range)
// welcome now equals "hello"

// substring
let greeting = "Hello, world!"
let index = greeting.firstIndex(of: ",") ?? greeting.endIndex
let beginning = greeting[..<index]
// beginning is "Hello"

// Convert the result to a String for long-term storage.
let newString = String(beginning)

3. 集合類型

Swift 提供三種集合類型,Arrays,Sets,Dictionarys。

用 var 定義的集合就是可變集合

Arrays

Arrays 存儲相同數(shù)據(jù)類型,元素有序,可重復(fù)

let a:[Any] = [1,2,"33"] 這個類型不一致是什么鬼?

var someInts = [Int]()
someInts.append(3)
someInts = []

var threeDoubles = Array(repeating: 0.0, count: 3)
// threeDoubles is of type [Double], and equals [0.0, 0.0, 0.0]
var anotherThreeDoubles = Array(repeating: 2.5, count: 3)
// anotherThreeDoubles is of type [Double], and equals [2.5, 2.5, 2.5]
var sixDoubles = threeDoubles + anotherThreeDoubles
// sixDoubles is inferred as [Double], and equals [0.0, 0.0, 0.0, 2.5, 2.5, 2.5]

var shoppingList: [String] = ["Eggs", "Milk"]
// 類型推導(dǎo)
var shoppingList = ["Eggs", "Milk"]

if shoppingList.isEmpty {
    print("The shopping list is empty.")
} else {
    print("The shopping list is not empty.")
}

// 用 "Bananas", "Apples" 替換 [4-6]位置的元素
shoppingList[4...6] = ["Bananas", "Apples"]

shoppingList.insert("Maple Syrup", at: 0)

let mapleSyrup = shoppingList.remove(at: 0)

// 遍歷
for item in shoppingList {
    print(item)
}
for (index, value) in shoppingList.enumerated() {
    print("Item \(index + 1): \(value)")
}

Sets

Sets 存儲相同數(shù)據(jù)類型,元素?zé)o序,不可重復(fù),Sets 中的元素必須可以計算哈希值,本質(zhì)上 Sets 是通過哈希表實現(xiàn)的。
Sets 定義類型關(guān)鍵字不能省略,因為表示語法和數(shù)組類似的

var letters = Set<Character>()
letters.insert("a")
// letters now contains 1 value of type Character
letters = []
// letters is now an empty set, but is still of type Set<Character>

var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]
var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"]

// 插入
favoriteGenres.insert("Jazz")

// 刪除
if let removedGenre = favoriteGenres.remove("Rock") {
    print("\(removedGenre)? I'm over it.")
} else {
    print("I never much cared for that.")
}
// Prints "Rock? I'm over it."

// 遍歷
for genre in favoriteGenres {
    print("\(genre)")
}

// 集合操作(交集,并集等)
let oddDigits: Set = [1, 3, 5, 7, 9]
let evenDigits: Set = [0, 2, 4, 6, 8]
let singleDigitPrimeNumbers: Set = [2, 3, 5, 7]

oddDigits.union(evenDigits).sorted()
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
oddDigits.intersection(evenDigits).sorted()
// []
oddDigits.subtracting(singleDigitPrimeNumbers).sorted()
// [1, 9]
oddDigits.symmetricDifference(singleDigitPrimeNumbers).sorted()
// [1, 2, 9]

Dictionaries

Dictionaries 存儲 key-value 對

var namesOfIntegers = [Int: String]()
namesOfIntegers[16] = "sixteen"
// namesOfIntegers now contains 1 key-value pair
namesOfIntegers = [:]
// namesOfIntegers is once again an empty dictionary of type [Int: String]

var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
var airports = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
airports["LHR"] = "London"

if let oldValue = airports.updateValue("Dublin Airport", forKey: "DUB") {
    print("The old value for DUB was \(oldValue).")
}

if let airportName = airports["DUB"] {
    print("The name of the airport is \(airportName).")
} else {
    print("That airport is not in the airports dictionary.")
}

if let removedValue = airports.removeValue(forKey: "DUB") {
    print("The removed airport's name is \(removedValue).")
} else {
    print("The airports dictionary does not contain a value for DUB.")
}
// Prints "The removed airport's name is Dublin Airport."

for (airportCode, airportName) in airports {
    print("\(airportCode): \(airportName)")
}

for airportCode in airports.keys {
    print("Airport code: \(airportCode)")
}
// Airport code: LHR
// Airport code: YYZ

for airportName in airports.values {
    print("Airport name: \(airportName)")
}
// Airport name: London Heathrow
// Airport name: Toronto Pearson

let airportCodes = [String](airports.keys)
// airportCodes is ["LHR", "YYZ"]

let airportNames = [String](airports.values)
// airportNames is ["London Heathrow", "Toronto Pearson"]

4. 控制流

For-In

for-in 可以用在序列上,比如 Arrays,Dictionarys,Sequence,Range等

let names = ["Anna", "Alex", "Brian", "Jack"]
for name in names {
    print("Hello, \(name)!")
}

let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
for (animalName, legCount) in numberOfLegs {
    print("\(animalName)s have \(legCount) legs")
}

for index in 1...5 {
    print("\(index) times 5 is \(index * 5)")
    // 5 10 15 20 25
}

var power = 10;
for _ in 1...5 { // 忽略 index 值
    power *= 2;
}

// 半開區(qū)間
let minutes = 60
for tickMark in 0..<minutes {
}
// 自定義步長
let minuteInterval = 5
for tickMark in stride(from: 0, to: minutes, by: minuteInterval) {
    // [0-60) (0, 5, 10, 15 ... 45, 50, 55)
}
let hours = 12
let hourInterval = 3
for tickMark in stride(from: 3, through: hours, by: hourInterval) {
    // [3-12] (3, 6, 9, 12)
}

While

var num = 10
while num > 0 {
    print("循環(huán)10次")
    num --;
}

repeat {
   print("循環(huán)10次")
    num --;
} while num > 0

條件語句

let temperatureInFahrenheit = 90
if temperatureInFahrenheit <= 32 {
    print("It's very cold. Consider wearing a scarf.")
} else if temperatureInFahrenheit >= 86 {
    print("It's really warm. Don't forget to wear sunscreen.")
} else {
    print("It's not that cold. Wear a t-shirt.")
}

Switch

在 Swift 中,switch 語法的 case 語句不會默認(rèn)接著執(zhí)行下一個case,不需要 break 來中斷,在 switch 中使用 break 會導(dǎo)致退出整個 switch 的執(zhí)行。要實現(xiàn) C 語言中那種 case-by-case 的效果,需要使用 fallthrough 關(guān)鍵字。

let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a", "A":
    print("The letter A")
    fallthrough
default:
    print("Not the letter A")
}
范圍匹配
let approximateCount = 62
let countedThings = "moons orbiting Saturn"
let naturalCount: String
switch approximateCount {
case 0:
    naturalCount = "no"
case 1..<5:
    naturalCount = "a few"
case 5..<12:
    naturalCount = "several"
default:
    naturalCount = "many"
}
print("There are \(naturalCount) \(countedThings).")
Tuples 匹配
let somePoint = (1, 1)
switch somePoint {
case (0, 0):
    print("\(somePoint) is at the origin")
case (_, 0):
    print("\(somePoint) is on the x-axis")
case (0, _):
    print("\(somePoint) is on the y-axis")
case (-2...2, -2...2):
    print("\(somePoint) is inside the box")
default:
    print("\(somePoint) is outside of the box")
}
// Prints "(1, 1) is inside the box"
Value Bindings
let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
    print("on the x-axis with an x value of \(x)")
case (0, let y):
    print("on the y-axis with a y value of \(y)")
case let (x, y):
    print("somewhere else at (\(x), \(y))")
}
// Prints "on the x-axis with an x value of 2"
Where
let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
    print("(\(x), \(y)) is on the line x == y")
case let (x, y) where x == -y:
    print("(\(x), \(y)) is on the line x == -y")
case let (x, y):
    print("(\(x), \(y)) is just some arbitrary point")
}
// Prints "(1, -1) is on the line x == -y"

控制轉(zhuǎn)移

continue,break,fallthrough 略

Labeled Statements
gameLoop: while square != finalSquare {
    diceRoll += 1
    if diceRoll == 7 { diceRoll = 1 }
    switch square + diceRoll {
    case finalSquare:
        break gameLoop
    case let newSquare where newSquare > finalSquare:
        continue gameLoop
    default:
        square += diceRoll
        square += board[square]
    }
}
print("Game over!")
guard

和 if 類似,必須提供 else 分支,暫時不明用這玩意的必要性。

func greet(person: [String: String]) {
    guard let name = person["name"] else {
        return
    }
    print("Hello \(name)!")
    guard let location = person["location"] else {
        print("I hope the weather is nice near you.")
        return
    }
    print("I hope the weather is nice in \(location).")
}
API 可用檢查
if #available(iOS 10, macOS 10.12, *) {
    // Use iOS 10 APIs on iOS, and use macOS 10.12 APIs on macOS
} else {
    // Fall back to earlier iOS and macOS APIs
}

5.Functions

無返回值,無參數(shù)函數(shù)
func sayHelloWorld()  {
    print("hello, world")
}
單條語句隱式返回
func greeting(person: String) -> String {
    "Hello, " + person + "!"
}
帶參數(shù),返回值,-> 是返回箭頭
func greet(_ person:String, from user: String, world: String = "Hello") -> String {
    return "to:\(person), greeting from:\(user), world:\(world)"
}
greet("Json", from:"End", world: "你好");
greet("Json", from:"End");

// 返回多個值
func minMax(array: [Int]) -> (min: Int, max: Int)? {
    var currentMin = array[0]
    var currentMax = array[0]
    for value in array[1..<array.count] {
        if value < currentMin {
            currentMin = value
        } else if value > currentMax {
            currentMax = value
        }
    }
    return (currentMin, currentMax)
}
可變參數(shù)
func arithmeticMean(_ numbers: Double...) -> Double {
    var total: Double = 0
    for number in numbers {
        total += number
    }
    return total / Double(numbers.count)
}
arithmeticMean(1, 2, 3, 4, 5)
// returns 3.0, which is the arithmetic mean of these five numbers
arithmeticMean(3, 8.25, 18.75)
// returns 10.0, which is the arithmetic mean of these three numbers
inout 參數(shù)

默認(rèn)情況,函數(shù)中的參數(shù)都是只讀,不能修改,要修改需要使用 inout 修飾

func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}

var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// Prints "someInt is now 107, and anotherInt is now 3"
函數(shù)類型
var mathFunction: (Int, Int) -> Int = addTwoInts

6. 閉包

語法
{ (parameters) -> return type in
    statements
}
幾個排序用法
// 數(shù)組排序
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
    return s1 > s2
})

// 根據(jù)上下文類型推導(dǎo)
// 因為是 String 類型的數(shù)組調(diào)用 sort 方法
reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )

// 單表達(dá)式隱式返回
reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )

// 參數(shù)速記,可省略參數(shù)列表和 in 語句
reversedNames = names.sorted(by: { $0 > $1 } )

// 運(yùn)算符函數(shù),String 類型有定義 > 運(yùn)算符函數(shù)
reversedNames = names.sorted(by: >)
尾隨閉包

當(dāng)閉包作為函數(shù)最后一個參數(shù)時,可以寫成尾隨閉包

func someFunctionThatTakesAClosure(closure: () -> Void) {
    // 函數(shù)體代碼
}

// 正常方式調(diào)用
someFunctionThatTakesAClosure(closure: {
    // 閉包實現(xiàn)代碼
})

// 尾隨閉包調(diào)用
someFunctionThatTakesAClosure() {
    // 閉包實現(xiàn)代碼
}

// 上面的排序可以修改成尾隨閉包調(diào)用
reversedNames = names.sorted() { $0 > $1 }

// 如果尾隨閉包是函數(shù)的唯一參數(shù),() 也可以省略
reversedNames = names.sorted { $0 > $1 }
變量捕捉

runningTotal 之所以會變是因為函數(shù)和閉包是引用類型

func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementer() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementer
}
let incrementByTen = makeIncrementer(forIncrement: 10)
incrementByTen()
// returns a value of 10
incrementByTen()
// returns a value of 20
incrementByTen()
// returns a value of 30
逃避閉包

簡單說就是一個閉包作為參數(shù)傳入函數(shù)后,并不是在函數(shù)體內(nèi)執(zhí)行,而是在函數(shù)返回后才會在某個時機(jī)執(zhí)行,比如異步請求,這時需要把這個閉包聲明為逃逸閉包,之所以要明確是不是逃逸閉包,應(yīng)該是為了內(nèi)存優(yōu)化管理

var completionHandlers = [() -> Void]()
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
    completionHandlers.append(completionHandler)
}
Autoclosures
var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
print(customersInLine.count)
// Prints "5"

let customerProvider = { customersInLine.remove(at: 0) }
print(customersInLine.count)
// Prints "5"

print("Now serving \(customerProvider())!")
// Prints "Now serving Chris!"
print(customersInLine.count)
// Prints "4"
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容