Swift語法1

目錄

Swif   數據類型  變量   可選類型  強制解析  自動解析   常量
類型標注   字面量  字符串  字符(Character)    數組     字典
函數  流程    guard   switch  閉包   枚舉  類  屬性    方法

Swift

1.類型安全
Swift 是一個類型安全(type safe)的語言。
由于 Swift 是類型安全的,所以它會在編譯你 的代碼時進行類型檢查(type checks),并把不匹配的類型標記為錯誤。這可以讓你在開發的時候盡早發現并修復錯誤。

2.類型別名
類型別名對當前的類型定義了另一個名字,類型別名通過使用 typealias 關鍵字來定義。語法格式如下:

typealias newname = type

例如以下定義了 Int 的類型別名為 Feet:

typealias Feet = Int

現在,我們可以通過別名來定義變量:

import Cocoa
typealias Feet = Int
var distance: Feet = 100
print(distance)

3.類型推斷
當你要處理不同類型的值時,類型檢查可以幫你避免錯誤。然而,這并不是說你每次聲明常量和變量的時候都需要顯式指定類型。
如果你沒有顯式指定類型,Swift 會使用類型推斷(type inference)來選擇合適的類型。
例如,如果你給一個新常量賦值42并且沒有標明類型,Swift 可以推斷出常量類型是Int,因為你給它賦的初始值看起來像一個整數:

let meaningOfLife = 42
// meaningOfLife 會被推測為 Int 類型

數據類型

1.基本數據類型有:整型:Int, 浮點型:Float, 雙精度浮點型:Double, 字符型:Character, 字符串型:String
定義常量:var x: Float = 42.0
定義變量:let y: Int = 12

注意:Swift可以推斷出數據的類型,所以在變量常量聲明的時候可以省略數據類型。

var x = 12
let y = 42.0

2.字符串的聲明:

let name : String = "綦帥鵬"
let age : Int = 10
print("My name is " + name + "," + String(age) + " years old!")
print("My name is \(name), \(age) years old!")

注意:
Swift中字符串可以通過"+"來拼接。
在Swift字符串中可以通過"(名稱)"來獲取常量、變量的值。

3.元組:元組是一系列不同類型數據的有序集合,可以包含不同的數據類型,通過".下標"來獲取對應的數據。

//元組

let student = ("綦帥鵬", 27, "打球")
print("學生:\(student.0), \(student.1)歲,喜歡\(student.2)!")

4.數組:數組是一系列相同類型的數據的有序集合,數組中的數據類型必須相同。

//數組,數組中數據的類型必須相同
var studentsName = ["張三", "李四", "王五"]
//添加數據
studentsName.append("趙六")
print(studentsName)
//添加多個數據,也可以理解為數組合并
studentsName += ["綦帥鵬", "綦朝暉"]
print(studentsName)
//添加數據到指定位置
studentsName.insert("廖騰逸", at: 0)
print(studentsName)
//修改數據
studentsName[1] = "廖雨琦"
print(studentsName)
//移除數據
studentsName.remove(at: 2)
print(studentsName)
//移除最后一個數據
studentsName.removeLast()
print(studentsName)
print(studentsName)
//移除所有數據
studentsName.removeAll()
print(studentsName)

5.字典:字典是一系列相同類型的數據的無序集合,數據是由鍵值對存在的,并且鍵不能為nil。

//字典:不能將key指定為nil
var product = ["name":"iPhone5", "size":"4寸"]
print(product)
//取值
print(product["name"]!)
//添加數據
product["address"] = "香港"
print(product)
//修改數據
product["size"] = "4英寸"
print(product)
//刪除數據
product["address"] = nil
print(product)

//字典數組搭配

print([[1, 2, 3], ["1", "2", "3"]])
print([["name": "張三", "address": "湖南"], ["name": "李四", "address": "北京"]])
//空數組
var arr: Array<Int> = []
arr.append(1)
print(arr)
var otherArr = [Int]()
otherArr += [2]
print(otherArr)
//空字典
var dic = Dictionary<String, String>()
dic["name"] = "張三"
print(dic)

6.數組與字典的遍歷

//數組遍歷
for item in [1, 2, 3] {
    print(item)
}
for (index, item) in [1, 2, 3].enumerated() {
    print("\(index): \(item)")
}
//遍歷字典
for (key, value) in ["name": "張三", "address": "湖南"] {
    print("\(key):\(value)")
}

變量

變量是一種使用方便的占位符,用于引用計算機內存地址。
Swift 每個變量都指定了特定的類型,該類型決定了變量占用內存的大小,不同的數據類型也決定可存儲值的范圍。

1.變量聲明
變量聲明意思是告訴編譯器在內存中的哪個位置上為變量創建多大的存儲空間。
在使用變量前,你需要使用 var 關鍵字聲明它,如下所示:

var variableName = <initial value>

2.變量命名
變量名可以由字母,數字和下劃線組成。
變量名需要以字母或下劃線開始。
Swift 是一個區分大小寫的語言,所以字母大寫與小寫是不一樣的。
3.變量輸出
變量和常量可以使用 print(swift 2 將 print 替換了 println) 函數來輸出。
在字符串中可以使用括號與反斜線來插入變量,如下實例:

import Cocoa
var name = "菜鳥教程"
var site = "http://www.runoob.com"
print("\(name)的官網地址為:\(site)")

Swift 可選(Optionals)類型

Swift 的可選(Optional)類型,用于處理值缺失的情況。可選表示"那兒有一個值,并且它等于 x "或者"那兒沒有值"。
Swfit語言定義后綴?作為命名類型Optional的簡寫,換句話說,以下兩種聲明是相等的:

var optionalInteger: Int?
var optionalInteger: Optional<Int>

在這兩種情況下,變量 optionalInteger 都是可選整數類型。注意,在類型和 ?之間沒有空格。
Optional 是一個含有兩種情況的枚舉,None 和 Some(T),用來表示可能有或可能沒有值。任何類型都可以明確聲明為(或者隱式轉換)可選類型。當聲明一個可選類型的時候,要確保用括號給 ? 操作符一個合適的范圍。例如,聲明可選整數數組,應該寫成 (Int[])? 寫成 Int[]? 會報錯。
當你聲明一個可選變量或者可選屬性的時候沒有提供初始值,它的值會默認為 nil。
可選項遵照 LogicValue 協議,因此可以出現在布爾環境中。在這種情況下,如果可選類型T?包含類型為T的任何值(也就是說它的值是 Optional.Some(T) ),這個可選類型等于 true,反之為 false。
如果一個可選類型的實例包含一個值,你可以用后綴操作符 !來訪問這個值,如下所示:

optionalInteger = 42
optionalInteger! // 42

使用操作符!去獲取值為nil的可選變量會有運行時錯誤。
你可以用可選鏈接和可選綁定選擇性執行可選表達式上的操作。如果值為nil,任何操作都不會執行,也不會有運行報錯。

注意:可選類型類似于Objective-C中指針的nil值,但是nil只對類(class)有用,而可選類型對所有的類型都可用,并且更安全。

強制解析

當你確定可選類型確實包含值之后,你可以在可選的名字后面加一個感嘆號(!)來獲取值。這個感嘆號表示"我知道這個可選有值,請使用它。"這被稱為可選值的強制解析(forced unwrapping)。
實例如下:

import Cocoa
var myString:String?
myString = "Hello, Swift!"
if myString != nil {
   print(myString)
}else{
   print("myString 值為 nil")
}
以上程序執行結果為:
Optional("Hello, Swift!")

強制解析可選值,使用感嘆號(!):

import Cocoa
var myString:String?
myString = "Hello, Swift!"
if myString != nil {
   // 強制解析
   print( myString! )
}else{
   print("myString 值為 nil")
}
以上程序執行結果為:
Hello, Swift!

注意:使用!來獲取一個不存在的可選值會導致運行時錯誤。使用!來強制解析值之前,一定要確定可選包含一個非nil的值。

自動解析

你可以在聲明可選變量時使用感嘆號(!)替換問號(?)。這樣可選變量在使用時就不需要再加一個感嘆號(!)來獲取值,它會自動解析。
實例如下:

import Cocoa
var myString:String!
myString = "Hello, Swift!"
if myString != nil {
   print(myString)
}else{
   print("myString 值為 nil")
}
以上程序執行結果為:
Hello, Swift!

可選綁定

使用可選綁定(optional binding)來判斷可選類型是否包含值,如果包含就把值賦給一個臨時常量或者變量。可選綁定可以用在if和while語句中來對可選類型的值進行判斷并把值賦給一個常量或者變量。
像下面這樣在if語句中寫一個可選綁定:

if let constantName = someOptional {
    statements
}

讓我們來看下一個簡單的可選綁定實例:

import Cocoa
var myString:String?
myString = "Hello, Swift!"
if let yourString = myString {
   print("你的字符串值為 - \(yourString)")
}else{
   print("你的字符串沒有值")
}
以上程序執行結果為:
你的字符串值為 - Hello, Swift!

Swift 常量

常量一旦設定,在程序運行時就無法改變其值。
常量可以是任何的數據類型如:整型常量,浮點型常量,字符常量或字符串常量。同樣也有枚舉類型的常量:
常量類似于變量,區別在于常量的值一旦設定就不能改變,而變量的值可以隨意更改。
常量聲明
常量使用關鍵字 let 來聲明,語法如下:

let constantName = <initial value>

以下是一個簡單的 Swift 程序中使用常量的實例:

import Cocoa
let constA = 42
print(constA)

1.常量命名
常量的命名可以由字母,數字和下劃線組成。
常量需要以字母或下劃線開始。
Swift 是一個區分大小寫的語言,所以字母大寫與小寫是不一樣的。
常量名也可以使用簡單的 Unicode 字符;
2.常量輸出
變量和常量可以使用 print(swift 2 將 print 替換了 println) 函數來輸出。
在字符串中可以使用括號與反斜線來插入常量

類型標注

當你聲明常量或者變量的時候可以加上類型標注(type annotation),說明常量或者變量中要存儲的值的類型。如果要添加類型標注,需要在常量或者變量名后面加上一個冒號和空格,然后加上類型名稱。

var constantName:<data type> = <optional initial value>

以下是一個簡單是實例演示了 Swift 中常量使用類型標注。需要注意的是常量定義時必須初始值:

import Cocoa
let constA = 42
print(constA)
let constB:Float = 3.14159
print(constB)

Swift 字面量

所謂字面量,就是指像特定的數字,字符串或者是布爾值這樣,能夠直接了當地指出自己的類型并為變量進行賦值的值。比如在下面:

let aNumber = 3         //整型字面量
let aString = "Hello"   //字符串字面量
let aBool = true        //布爾值字面量

1.布爾型字面量
布爾型字面量的默認類型是 Bool。
布爾值字面量有三個值,它們是 Swift 的保留關鍵字:

true 表示真。
false 表示假。
nil 表示沒有值。

2.字符串型字面量
字符串型字面量由被包在雙引號中的一串字符組成,形式如下:

"characters"

字符串型字面量中不能包含未轉義的雙引號 (")、未轉義的反斜線(\)、回車符或換行符。

\0  空字符
\\  反斜線 \
\b  退格(BS) ,將當前位置移到前一列
\f  換頁(FF),將當前位置移到下頁開頭
\n  換行符
\r  回車符
\t  水平制表符
\v  垂直制表符
\'  單引號
\"  雙引號
\000    1到3位八進制數所代表的任意字符
\xhh... 1到2位十六進制所代表的任意字符

字符串

1.創建字符串
你可以通過使用字符串字面量或 String 類的實例來創建一個字符串:

// 使用字符串字面量
var stringA = "Hello, World!"
print( stringA )

// String 實例化
var stringB = String("Hello, World!")
print( stringB )

2.空字符串
你可以使用空的字符串字面量賦值給變量或初始化一個String類的實例來初始值一個空的字符串。 我們可以使用字符串屬性 isEmpty 來判斷字符串是否為空:

// 使用字符串字面量創建空字符串
var stringA = ""
if stringA.isEmpty {
   print( "stringA 是空的" )
} else {
   print( "stringA 不是空的" )
}

// 實例化 String 類來創建空字符串
let stringB = String()
if stringB.isEmpty {
   print( "stringB 是空的" )
} else {
   print( "stringB 不是空的" )
}

3.字符串常量
你可以將一個字符串賦值給一個變量或常量,變量是可修改的,常量是不可修改的。

// stringA 可被修改
var stringA = "菜鳥教程:"
stringA += "http://www.runoob.com"
print( stringA )

// stringB 不能修改
let stringB = String("菜鳥教程:")
stringB += "http://www.runoob.com"
print( stringB )
以上程序執行輸出結果會報錯,以為 stringB 為常量是不能被修改的

4.字符串中插入值
字符串插值是一種構建新字符串的方式,可以在其中包含常量、變量、字面量和表達式。 您插入的字符串字面量的每一項都在以反斜線為前綴的圓括號中:

var varA   = 20
let constA = 100
var varC:Float = 20.0
var stringA = "\(varA) 乘于 \(constA) 等于 \(varC * 100)"
print( stringA )
以上程序執行輸出結果為:
20 乘于 100 等于 2000.0

5.字符串連接
字符串可以通過 + 號來連接,實例如下:

let constA = "菜鳥教程:"
let constB = "http://www.runoob.com"
var stringA = constA + constB
print( stringA )

6.字符串長度
字符串長度使用 String.characters.count 屬性來計算,實例如下:

var varA   = "www.runoob.com"
print( "\(varA), 長度為 \(varA.characters.count)" )
以上程序執行輸出結果為:
www.runoob.com, 長度為 14

7.字符串比較
你可以使用 == 來比較兩個字符串是否相等:

var varA   = "Hello, Swift!"
var varB   = "Hello, World!"
if varA == varB {
   print( "\(varA) 與 \(varB) 是相等的" )
} else {
   print( "\(varA) 與 \(varB) 是不相等的" )
}
以上程序執行輸出結果為:
Hello, Swift! 與 Hello, World! 是不相等的

8.Unicode 字符串
Unicode 是一個國際標準,用于文本的編碼,Swift 的 String 類型是基于 Unicode建立的。你可以循環迭代出字符串中 UTF-8 與 UTF-16 的編碼,實例如下:

var unicodeString   = "菜鳥教程"
print("UTF-8 編碼: ")
for code in unicodeString.utf8 {
   print("\(code) ")
}
print("\n")
print("UTF-16 編碼: ")
for code in unicodeString.utf16 {
   print("\(code) ")
}

9.字符串函數及運算符

  • isEmpty 判斷字符串是否為空,返回布爾值
  • hasPrefix(prefix: String) 檢查字符串是否擁有特定前綴
  • hasSuffix(suffix: String) 檢查字符串是否擁有特定后綴。
  • Int(String) 轉換字符串數字為整型。 實例:
let myString: String = "256"
let myInt: Int? = Int(myString)
  • String.characters.count 計算字符串的長度
  • < 比較兩個字符串,對兩個字符串的字母逐一比較。
  • += 連接操作符兩邊的字符串并將新字符串賦值給左邊的操作符變量
    • 連接兩個字符串,并返回一個新的字符串
  • == 判斷兩個字符串是否相等

Swift 字符(Character)

Swift 的字符是一個單一的字符字符串字面量,數據類型為 Character。
以下實例列出了兩個字符實例:

let char1: Character = "A"
  • 如果你想在 Character(字符) 類型的常量中存儲更多的字符,則程序執行會報錯,如下所示:
// Swift 中以下賦值會報錯
let char: Character = "AB"
  • Swift 中不能創建空的 Character(字符) 類型變量或常量:
// Swift 中以下賦值會報錯
let char1: Character = ""
  • 遍歷字符串中的字符
    Swift 的 String 類型表示特定序列的 Character(字符) 類型值的集合。 每一個字符值代表一個 Unicode 字符。
    您可通過for-in循環來遍歷字符串中的characters屬性來獲取每一個字符的值:
for ch in "Runoob".characters {
    print(ch)
}
  • 字符串連接字符
    以下實例演示了使用 String 的 append() 方法來實現字符串連接字符:
var varA:String = "Hello "
let varB:Character = "G"
varA.append( varB )
print("varC  =  \(varA)")
以上程序執行輸出結果為:
varC  =  Hello G

Swift 數組

Swift 數組使用有序列表存儲同一類型的多個值。相同的值可以多次出現在一個數組的不同位置中。
Swift 數組會強制檢測元素的類型,如果類型不同則會報錯,Swift 數組應該遵循像Array<Element>這樣的形式,其中Element是這個數組中唯一允許存在的數據類型。
如果創建一個數組,并賦值給一個變量,則創建的集合就是可以修改的。這意味著在創建數組后,可以通過添加、刪除、修改的方式改變數組里的項目。如果將一個數組賦值給常量,數組就不可更改,并且數組的大小和內容都不可以修改。
1.創建數組
我們可以使用構造語法來創建一個由特定數據類型構成的空數組:

var someArray = [SomeType]()

以下是創建一個初始化大小數組的語法:

var someArray = [SomeType](repeating: InitialValue, count: NumbeOfElements)

以下實例創建了一個類型為 Int ,數量為 3,初始值為 0 的空數組:

var someInts = [Int](repeating: 0, count: 3)

以下實例創建了含有三個元素的數組:

var someInts:[Int] = [10, 20, 30]

2.訪問數組
我們可以根據數組的索引來訪問數組的元素,語法如下:

var someVar = someArray[index]

index 索引從 0 開始,及索引 0 對應第一個元素,索引 1 對應第二個元素,以此類推。
我們可以通過以下實例來學習如何創建,初始化,訪問數組:

var someInts = [Int](repeating: 10, count: 3)
var someVar = someInts[0]
print( "第一個元素的值 \(someVar)" )

3.修改數組
你可以使用 append() 方法或者賦值運算符 += 在數組末尾添加元素,如下所示,我們初始化一個數組,并向其添加元素,也可以通過索引修改數組元素的值:

var someInts = [Int]()
someInts.append(20)
someInts.append(30)
someInts += [40]
var someVar = someInts[0]
print( "第一個元素的值 \(someVar)" )
print( "第二個元素的值 \(someInts[1])" )
print( "第三個元素的值 \(someInts[2])" )

// 修改最后一個元素
someInts[2] = 50
print( "第三個元素的值 \(someInts[2])" )

以上程序執行輸出結果為:
第一個元素的值 20
第二個元素的值 30
第三個元素的值 40
第三個元素的值 50

4.遍歷數組

  • 使用for-in循環來遍歷所有數組中的數據項:
var someStrs = [String]()
someStrs.append("Apple")
someStrs.append("Amazon")
someStrs.append("Runoob")
someStrs += ["Google"]

for item in someStrs {
   print(item)
}
  • 如果我們同時需要每個數據項的值和索引值,可以使用 String 的 enumerate() 方法來進行數組遍歷。實例如下:
var someStrs = [String]()
someStrs.append("Apple")
someStrs.append("Amazon")
someStrs.append("Runoob")
someStrs += ["Google"]

for (index, item) in someStrs.enumerated() {
    print("在 index = \(index) 位置上的值為 \(item)")
}
以上程序執行輸出結果為:
在 index = 0 位置上的值為 Apple
在 index = 1 位置上的值為 Amazon
在 index = 2 位置上的值為 Runoob
在 index = 3 位置上的值為 Google

5.合并數組
我們可以使用加法操作符(+)來合并兩種已存在的相同類型數組。新數組的數據類型會從兩個數組的數據類型中推斷出來:

var intsA = [Int](repeating: 2, count:2)
var intsB = [Int](repeating: 1, count:3)
var intsC = intsA + intsB
for item in intsC {
    print(item)
}

6.count 屬性
使用 count 屬性來計算數組元素個數:

var intsB = [Int](count:3, repeatedValue: 1)
print("intsB 元素個數為 \(intsB.count)")

7.isEmpty 屬性
我們可以通過只讀屬性 isEmpty 來判斷數組是否為空,返回布爾值:

var intsA = [Int](count:2, repeatedValue: 2)
var intsB = [Int](count:3, repeatedValue: 1)
var intsC = [Int]()
print("intsA.isEmpty = \(intsA.isEmpty)")
print("intsB.isEmpty = \(intsB.isEmpty)")
print("intsC.isEmpty = \(intsC.isEmpty)")
以上程序執行輸出結果為:
intsA.isEmpty = false
intsB.isEmpty = false
intsC.isEmpty = true

字典

Swift 字典用來存儲無序的相同類型數據的集合,Swift 字典會強制檢測元素的類型,如果類型不同則會報錯。
Swift 字典每個值(value)都關聯唯一的鍵(key),鍵作為字典中的這個值數據的標識符。
和數組中的數據項不同,字典中的數據項并沒有具體順序。我們在需要通過標識符(鍵)訪問數據的時候使用字典,這種方法很大程度上和我們在現實世界中使用字典查字義的方法一樣。
Swift 字典的key沒有類型限制可以是整型或字符串,但必須是唯一的。
如果創建一個字典,并賦值給一個變量,則創建的字典就是可以修改的。這意味著在創建字典后,可以通過添加、刪除、修改的方式改變字典里的項目。如果將一個字典賦值給常量,字典就不可修改,并且字典的大小和內容都不可以修改。

1.創建字典
我們可以使用以下語法來創建一個特定類型的空字典:

var someDict =  [KeyType: ValueType]()

以下是創建一個空字典,鍵的類型為 Int,值的類型為 String 的簡單語法:

var someDict = [Int: String]()

以下為創建一個字典的實例:

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]

2.訪問字典
我們可以根據字典的索引來訪問數組的元素,語法如下:

var someVar = someDict[key]

我們可以通過以下實例來學習如何創建,初始化,訪問字典:

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var someVar = someDict[1]

3.修改字典
我們可以使用 updateValue(forKey:) 增加或更新字典的內容。如果 key 不存在,則添加值,如果存在則修改 key 對應的值。updateValue(_:forKey:)方法返回Optional值。實例如下:

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var oldVal = someDict.updateValue("One 新的值", forKey: 1)
var someVar = someDict[1]

4.移除 Key-Value 對
使用 removeValueForKey() 方法來移除字典 key-value 對。如果 key 存在該方法返回移除的值,如果不存在返回 nil 。實例如下:

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var removedValue = someDict.removeValue(forKey: 2)

5.遍歷字典

  • 可以使用 for-in 循環來遍歷某個字典中的鍵值對。實例如下:
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
for (key, value) in someDict {
   print("字典 key \(key) -  字典 value \(value)")
}
  • 可以使用enumerate()方法來進行字典遍歷,返回的是字典的索引及 (key, value) 對,實例如下:
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
for (key, value) in someDict.enumerate() {
    print("字典 key \(key) -  字典 (key, value) 對 \(value)")
}

6.字典轉換為數組
你可以提取字典的鍵值(key-value)對,并轉換為獨立的數組。實例如下:

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
let dictKeys = [Int](someDict.keys)
let dictValues = [String](someDict.values)

print("輸出字典的鍵(key)")
for (key) in dictKeys {
    print("\(key)")
}
print("輸出字典的值(value)")
for (value) in dictValues {
    print("\(value)")
}

7.count 屬性
可以使用只讀的 count 屬性來計算字典有多少個鍵值對:

var someDict1:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
print("someDict1 含有 \(someDict1.count) 個鍵值對")

8.isEmpty 屬性
Y我們可以通過只讀屬性 isEmpty 來判斷字典是否為空,返回布爾值:

var someDict1:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
print("someDict1 = \(someDict1.isEmpty)")

函數

Swift 函數用來完成特定任務的獨立的代碼塊。
Swift使用一個統一的語法來表示簡單的C語言風格的函數到復雜的Objective-C語言風格的方法。
函數聲明: 告訴編譯器函數的名字,返回類型及參數。
函數定義: 提供了函數的實體。
Swift 函數包含了參數類型及返回值類型;

1.函數定義
Swift 定義函數使用關鍵字 func。
定義函數的時候,可以指定一個或多個輸入參數和一個返回值類型。
每個函數都有一個函數名來描述它的功能。通過函數名以及對應類型的參數值來調用這個函數。函數的參數傳遞的順序必須與參數列表相同。
函數的實參傳遞的順序必須與形參列表相同,-> 后定義函數的返回值類型。
語法

func funcname(形參) -> returntype
{
   Statement1
   Statement2
   ……
   Statement N
   return parameters
}

以下我們定義了一個函數名為 runoob 的函數,形參的數據類型為 String,返回值也為 String:

func runoob(site: String) -> String {
    return (site)
}
print(runoob(site: "www.runoob.com"))
以上程序執行輸出結果為:
www.runoob.com

2.函數調用
可以通過函數名以及對應類型的參數值來調用函數,函數的參數傳遞的順序必須與參數列表相同。
3.函數參數
函數可以接受一個或者多個參數,這些參數被包含在函數的括號之中,以逗號分隔。
以下實例向函數 runoob 傳遞站點名 name 和站點地址 site:

func runoob(name: String, site: String) -> String {
    return name + site
}
print(runoob(name: "菜鳥教程:", site: "www.runoob.com"))
以上程序執行輸出結果為:
菜鳥教程:www.runoob.com

4.不帶參數函數
我們可以創建不帶參數的函數。
語法:

func funcname() -> datatype {
   return datatype
}

實例

func sitename() -> String {
    return "菜鳥教程"
}
print(sitename())
以上程序執行輸出結果為:
菜鳥教程

5.元組作為函數返回值
函數返回值類型可以是字符串,整型,浮點型等。
元組與數組類似,不同的是,元組中的元素可以是任意類型,使用的是圓括號。
你可以用元組(tuple)類型讓多個值作為一個復合值從函數中返回。
如果你不確定返回的元組一定不為nil,那么你可以返回一個可選的元組類型。
你可以通過在元組類型的右括號后放置一個問號來定義一個可選元組,例如(Int, Int)?或(String, Int, Bool)?

注意:
可選元組類型如(Int, Int)?與元組包含可選類型如(Int?, Int?)是不同的.可選的元組類型,整個元組是可選的,而不只是元組中的每個元素值。

前面的minMax(:)函數返回了一個包含兩個Int值的元組。但是函數不會對傳入的數組執行任何安全檢查,如果array參數是一個空數組,如上定義的minMax(:)在試圖訪問array[0]時會觸發一個運行時錯誤。
為了安全地處理這個"空數組"問題,將minMax(_:)函數改寫為使用可選元組返回類型,并且當數組為空時返回nil:

func minMax(array: [Int]) -> (min: Int, max: Int)? {
    if array.isEmpty { return nil }
    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)
}
if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) {
    print("最小值為 \(bounds.min),組大值為 \(bounds.max)")
}
以上程序執行輸出結果為:
最小值為 -6,組大值為 109

6.沒有返回值函數
下面是 runoob(_:) 函數的另一個版本,這個函數接收菜鳥教程官網網址參數,沒有指定返回值類型,并直接輸出 String 值,而不是返回它:

func runoob(site: String) {
    print("菜鳥教程官網:\(site)")
}
runoob(site: "http://www.runoob.com")
以上程序執行輸出結果為:
菜鳥教程官網:http://www.runoob.com

7.函數參數名稱
函數參數都有一個外部參數名和一個局部參數名。

  • 局部參數名
    局部參數名在函數的實現內部使用。
func sample(number: Int) {
   println(number)
}

以上實例中 number 為局部參數名,只能在函數體內使用。

  • 外部參數名
    你可以在局部參數名前指定外部參數名,中間以空格分隔,外部參數名用于在函數調用時傳遞給函數的參數。
    如下你可以定義以下兩個函數參數名并調用它:
func pow(firstArg a: Int, secondArg b: Int) -> Int {
   var res = a
   for _ in 1..<b {
      res = res * a
   }
   print(res)
   return res
}
pow(firstArg:5, secondArg:3)
以上程序執行輸出結果為:
125

注意: 如果你提供了外部參數名,那么函數在被調用時,必須使用外部參數名。

8.可變參數
可變參數可以接受零個或多個值。函數調用時,你可以用可變參數來指定函數參數,其數量是不確定的。
可變參數通過在變量類型名后面加入(...)的方式來定義。

func vari<N>(members: N...){
    for i in members {
        print(i)
    }
}
vari(members: 4,3,5)
vari(members: 4.5, 3.1, 5.6)

9.常量,變量及 I/O 參數
一般默認在函數中定義的參數都是常量參數,也就是這個參數你只可以查詢使用,不能改變它的值。
如果想要聲明一個變量參數,可以在參數定義前加 inout 關鍵字,這樣就可以改變這個參數的值了。
例如:

func  getName(_ name: inout String).........

此時這個 name 值可以在函數中改變。
一般默認的參數傳遞都是傳值調用的,而不是傳引用。所以傳入的參數在函數內改變,并不影響原來的那個參數。傳入的只是這個參數的副本。
當傳入的參數作為輸入輸出參數時,需要在參數名前加 & 符,表示這個值可以被函數修改。
實例

func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}
var x = 1
var y = 5
swapTwoInts(&x, &y)
print("x 現在的值 \(x), y 現在的值 \(y)")
swapTwoInts(_:_:) 函數簡單地交換 a 與 b 的值。該函數先將 a 的值存到一個臨時常量 temporaryA 中,然后將 b 的值賦給 a,最后將 temporaryA 賦值給 b。
需要注意的是,someInt 和 anotherInt 在傳入 swapTwoInts(_:_:) 函數前,都加了 & 的前綴。
以上程序執行輸出結果為:
x 現在的值 5, y 現在的值 1

10.函數類型及使用
每個函數都有種特定的函數類型,由函數的參數類型和返回類型組成。

func inputs(no1: Int, no2: Int) -> Int {
   return no1/no2
}
  • 函數也可以定義一個沒有參數,也沒有返回值的函數,如下所示:
func inputstr() {
   print("菜鳥教程")
   print("www.runoob.com")
}
inputstr()
以上程序執行輸出結果為:
菜鳥教程
www.runoob.com
  • 函數類型作為參數類型、函數類型作為返回類型
    我們可以將函數作為參數傳遞給另外一個參數:
func sum(a: Int, b: Int) -> Int {
    return a + b
}
var addition: (Int, Int) -> Int = sum
print("輸出結果: \(addition(40, 89))")
func another(addition: (Int, Int) -> Int, a: Int, b: Int) {
    print("輸出結果: \(addition(a, b))")
}
another(addition: sum, a: 10, b: 20)
以上程序執行輸出結果為:
輸出結果: 129
輸出結果: 30
  • 函數嵌套
    函數嵌套指的是函數內定義一個新的函數,外部的函數可以調用函數內定義的函數。
    實例如下:
func calcDecrement(forDecrement total: Int) -> () -> Int {
   var overallDecrement = 0
   func decrementer() -> Int {
      overallDecrement -= total
      return overallDecrement
   }
   return decrementer
}
let decrem = calcDecrement(forDecrement: 30)
print(decrem())
以上程序執行輸出結果為:
-30

inputs 函數類型有兩個 Int 型的參數(no1、no2)并返回一個 Int 型的值。

流程控制

1.for循環

let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for num in arr {
    print(num)
}
for item in 1...10 {
    print(item)
}
for item in 1..<10 {
    print(item)
}
for item in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].reversed() {
    print(item)
}

2.if…else…選擇

let lightColor = "red"
if lightColor == "red"
{
    print("Stop!")
}
else
{
    print("Go!")
}

3.while循環和switch…case…選擇

let limit = 75
var speed = 0
while speed < 100 {
    speed += 1
    switch speed {
    case 0..<20:
        print("太慢啦!")
    case 20..<40:
        print("快點行嗎!")
    case 40..<60:
        print("速度起來啦!")
    case 60...limit:
        print("別超速呀,我的哥!")
    default:
        print("超速啦,我的哥!")
    }
    if speed > limit {
        break
    }
}
  • 注意:在Swift中可以不需要使用break關鍵字
    在Swift的判斷句中必須有明確的真假
    不再有非0即真
    必須有明確的Bool值
    Bool有兩個取值:false/true

  • 控制語句 描述

    • continue 語句 :告訴一個循環體立刻停止本次循環迭代,重新開始下次循環迭代。
    • break 語句 :中斷當前循環。
    • fallthrough 語句 :如果在一個case執行完后,繼續執行下面的case,需要使用fallthrough(貫穿)關鍵字。

guard的使用

guard是Swift2.0新增的語法
它與if語句非常類似,它設計的目的是提高程序的可讀性
guard語句必須帶有else語句,它的語法如下:

當條件表達式為true時候跳過else語句中的內容,執行語句組內容

  guard 條件表達式 else {
      // 條換語句
      break
  }
  語句組

例子

    var age = 18
    func online(age : Int) -> Void {
        guard age >= 18 else {
            print("回家去")
            return
        }
        print("可以上網")
    }
    online(age)

switch

Switch作為選擇結構中必不可少的語句也被加入到了Swift中
只要有過編程經驗的人對Switch語句都不會感到陌生
但蘋果對Switch進行了大大的增強,使其擁有其他語言中沒有的特性
switch的簡單使用
基本用法和OC用法一致
不同之處:
switch后可以不跟()
case后可以不跟break(默認會有break)
例子:

    let sex = 0
    switch sex {
    case 0 :
        print("男")
    case 1 :
        print("女")
    default :
        print("其他")
    }

簡單使用補充:
一個case判斷中,可以判斷多個值
多個值以,隔開

  let sex = 0
  switch sex {
  case 0, 1:
      print("正常人")
  default:
      print("其他")
  }

簡單使用補充:
如果希望出現之前的case穿透,則可以使用關鍵字fallthrough

  let sex = 0
  switch sex {
  case 0:
      fallthrough
  case 1:
      print("正常人")
  default:
      print("其他")
  }

Switch支持多種數據類型
浮點型的switch判斷

    let f = 3.14
    switch f {
    case 3.14:
        print("π")
    default:
        print("not π")
    }

支持字符串類型

  let m = 5
  let n = 10
  var result = 0
  let opration = "+"

  switch opration {
      case "+":
          result = m + n
      case "-":
          result = m - n
      case "*":
          result = m * n
      case "/":
          result = m / n
  default:
      result = 0
  }
  print(result)

switch支持區間判斷
什么是區間?
通常我們指的是數字區間:010,100200
swift中的區間常見有兩種
半開半閉區間:0..<10 表示:0~9,不包括10
閉區間:0...10 表示:0~10

  let score = 88
  switch score {
  case 0..<60:
      print("不及格")
  case 60..<80:
      print("幾個")
  case 80..<90:
      print("良好")
  case 90..<100:
      print("優秀")
  default:
      print("滿分")
  }

函數

1.函數的定義:func 函數名(參數1名: 參數類型, 參數2名: 參數類型) -> 返回值類型

func add(num: Int, otherNum: Int) -> Int {
    return num + otherNum
}
print(add(num: 10, otherNum: 20))

2.參數個數變化的函數定義:在函數的最后一個參數中用...來添加多個參數

//可變參數,只能在函數的最后一個參數中用...來添加多個參數
func addAllNums(nums: Float...) -> Float {
    var result : Float = 0.0
    for item in nums {
        result += item;
    }

    return result
}
print(addAllNums(nums: 10, 20, 30, 40, 50, 60, 70, 80, 90, 100))

3.帶默認參數的函數

//默認參數
func circleArea(r: Double = 10) -> Double{
    return M_PI*r*r
}
print(circleArea())
print(circleArea(r: 100))

4.高階函數:Swift中函數可以做參數也可以做返回值

//找出最大數
func findMax(nums: Double...) -> Double {
    var result : Double = -Double.infinity//負無窮大
    for item in nums {
        if item > result {
            result = item
        }
    }

    return result
}
print(findMax(nums: 12, 3333, 32413, 324, 34124, 3432))
//找出最小數
func findMin(nums: Double...) -> Double {
    var result : Double = Double.infinity
    for item in nums {
        if item < result {
            result = item
        }
    }

    return result
}
print(findMin(nums: 12, 3333, 32413, 324, 34124, 3432))

//函數返回函數
func findNum(type: String) -> (Double...) -> (Double) {
    if type == "max" || type == "Max" {
        return findMax
    }
    return findMin
}
print(findNum(type: "Max")(1,2,3,4,32,32,4,34,23) + findNum(type: "Min")(2,32,323,233,1,323))

5.函數嵌套:在函數中定義使用函數

//函數嵌套
func randomNum(type:String) -> Int {
    func randomPositive() -> Int {
        return Int(arc4random())
    }
    func randomNegative() -> Int {
        return -(Int)(arc4random())
    }
    if type == "randomPositive" {
        return randomPositive()
    }
    return randomNegative()
}
print(randomNum(type: "randomPositive"))
print(randomNum(type: "randomNegative"))

注意:函數中的參數inout關鍵字會改變函數體外的變量值,同時在調用該函數的時候,此參數需傳地址而不是值。

//變量參數,inout關鍵字會改變函數體外的變量值

func ascendingSort(num1: inout Int, num2: inout Int, num3: inout Int) -> [Int]
{
    var temp : Int
    if num1 > num2 {
        temp = num1;
        num1 = num2;
        num2 = temp;
    }
    if num2 > num3 {
        temp = num2;
        num2 = num3;
        num3 = temp;
    }
    return [num1, num2, num3]
}
var num1 = 3
var num2 = 2
var num3 = 4
print(ascendingSort(num1: &num1, num2: &num2, num3: &num3))
print([num1, num2, num3])

6.類的析構函數
析構函數
Swift 會自動釋放不再需要的實例以釋放資源
Swift 通過自動引用計數(ARC)處理實例的內存管理
當引用計數為0時,系統會自動調用析構函數(不可以手動調用)
通常在析構函數中釋放一些資源(如移除通知等操作)
析構函數的寫法

    deinit {
        // 執行析構過程
    }

閉包

閉包(Closures)是自包含的功能代碼塊,可以在代碼中使用或者用來作為參數傳值。
Swift 中的閉包與 C 和 Objective-C 中的代碼塊(blocks)以及其他一些編程語言中的 匿名函數比較相似。
全局函數和嵌套函數其實就是特殊的閉包。

  • 閉包的形式有:

    • 全局函數 嵌套函數 閉包表達式
    • 有名字但不能捕獲任何值。 有名字,也能捕獲封閉函數內的值。 無名閉包,使用輕量級語法,可以根據上下文環境捕獲值。
  • Swift中的閉包有很多優化的地方:

    • 根據上下文推斷參數和返回值類型
    • 從單行表達式閉包中隱式返回(也就是閉包體只有一行代碼,可以省略return)
    • 可以使用簡化參數名,如0,1(從0開始,表示第i個參數...)
    • 提供了尾隨閉包語法(Trailing closure syntax)
  • 語法
    以下定義了一個接收參數并返回指定類型的閉包語法:

{(parameters) -> return type in
   statements
}

實例

let studname = { print("Swift 閉包實例。") }
studname()
以上程序執行輸出結果為:
Swift 閉包實例。

1.說明:閉包與函數類似,就是一個代碼塊分裝了其所處環境的所有狀態。在閉包之前聲明的所有變量常量都會被閉包所捕獲,從本質上說閉包保留定義它時的程序狀態。函數是有名稱的閉包,閉包是無名稱的函數。
2.定義一個計算單利的閉包

var simpleClosure = {(amount: Double, interestRate: inout Double, years: Int) -> Double in
    interestRate = interestRate/100
    var interest = Double(years) * interestRate * amount

    return interest + amount
}

3.高階函數就是使用(閉包或函數)作為參數或返回值

//閉包做函數的參數
func loanCalculator(amount: Double, interestRate: inout Double, years: Int, calculator: (Double, inout Double, Int) -> Double) -> Double
{
    return calculator(amount, &interestRate, years)
}
var rate : Double = 3.875
print(loanCalculator(amount: 10000, interestRate: &rate, years: 5, calculator: simpleClosure))

4.sorted 方法
Swift 標準庫提供了名為 sorted(by:) 的方法,會根據您提供的用于排序的閉包函數將已知類型數組中的值進行排序。
排序完成后,sorted(by:) 方法會返回一個與原數組大小相同,包含同類型元素且元素已正確排序的新數組。原數組不會被 sorted(by:) 方法修改。

  • sorted(by:)方法需要傳入兩個參數:
    • 已知類型的數組
    • 閉包函數,該閉包函數需要傳入與數組元素類型相同的兩個值,并返回一個布爾類型值來表明當排序結束后傳入的第一個參數排在第二個參數前面還是后面。如果第一個參數值出現在第二個參數值前面,排序閉包函數需要返回 true,反之返回 false。
      實例
let names = ["AT", "AE", "D", "S", "BE"]
// 使用普通函數(或內嵌函數)提供排序功能,閉包函數類型需為(String, String) -> Bool。
func backwards(s1: String, s2: String) -> Bool {
    return s1 > s2
}
var reversed = names.sorted(by: backwards)
print(reversed)
以上程序執行輸出結果為:
["S", "D", "BE", "AT", "AE"]

如果第一個字符串 (s1) 大于第二個字符串 (s2),backwards函數返回true,表示在新的數組中s1應該出現在s2前。 對于字符串中的字符來說,"大于" 表示 "按照字母順序較晚出現"。 這意味著字母"B"大于字母"A",字符串"S"大于字符串"D"。 其將進行字母逆序排序,"AT"將會排在"AE"之前。

  • 參數名稱縮寫
    Swift 自動為內聯函數提供了參數名稱縮寫功能,您可以直接通過0,1,$2來順序調用閉包的參數。
    實例
let names = ["AT", "AE", "D", "S", "BE"]
var reversed = names.sorted( by: { $0 > $1 } )
print(reversed)
$0和$1表示閉包中第一個和第二個String類型的參數。
以上程序執行輸出結果為:
["S", "D", "BE", "AT", "AE"]

如果你在閉包表達式中使用參數名稱縮寫, 您可以在閉包參數列表中省略對其定義, 并且對應參數名稱縮寫的類型會通過函數類型進行推斷。in 關鍵字同樣也可以被省略.

  • 運算符函數
    實際上還有一種更簡短的方式來撰寫上面例子中的閉包表達式。
    Swift 的String類型定義了關于大于號 (>) 的字符串實現,其作為一個函數接受兩個String類型的參數并返回Bool類型的值。 而這正好與sort(_:)方法的第二個參數需要的函數類型相符合。 因此,您可以簡單地傳遞一個大于號,Swift可以自動推斷出您想使用大于號的字符串函數實現:
let names = ["AT", "AE", "D", "S", "BE"]
var reversed = names.sorted(by: >)
print(reversed)
以上程序執行輸出結果為:
["S", "D", "BE", "AT", "AE"]
  • 尾隨閉包
    尾隨閉包是一個書寫在函數括號之后的閉包表達式,函數支持將其作為最后一個參數調用。
func someFunctionThatTakesAClosure(closure: () -> Void) {
    // 函數體部分
}
// 以下是不使用尾隨閉包進行函數調用
someFunctionThatTakesAClosure({
    // 閉包主體部分
})
// 以下是使用尾隨閉包進行函數調用
someFunctionThatTakesAClosure() {
  // 閉包主體部分
}

實例

let names = ["AT", "AE", "D", "S", "BE"]
//尾隨閉包
var reversed = names.sorted() { $0 > $1 }
print(reversed)
sort() 后的 { $0 > $1} 為尾隨閉包。
以上程序執行輸出結果為:
["S", "D", "BE", "AT", "AE"]

注意: 如果函數只需要閉包表達式一個參數,當您使用尾隨閉包時,您甚至可以把()省略掉。
reversed = names.sorted { 0 >1 }

  • 捕獲值
    閉包可以在其定義的上下文中捕獲常量或變量。
    即使定義這些常量和變量的原域已經不存在,閉包仍然可以在閉包函數體內引用和修改這些值。
    Swift最簡單的閉包形式是嵌套函數,也就是定義在其他函數的函數體內的函數。
    嵌套函數可以捕獲其外部函數所有的參數以及定義的常量和變量。
    看這個例子:
func makeIncrementor(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementor() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return increment or
}

一個函數makeIncrementor ,它有一個Int型的參數amout, 并且它有一個外部參數名字forIncremet,意味著你調用的時候,必須使用這個外部名字。返回值是一個()-> Int的函數。
函數題內,聲明了變量runningTotal 和一個函數incrementor。
incrementor函數并沒有獲取任何參數,但是在函數體內訪問了runningTotal和amount變量。這是因為其通過捕獲在包含它的函數體內已經存在的runningTotal和amount變量而實現。
由于沒有修改amount變量,incrementor實際上捕獲并存儲了該變量的一個副本,而該副本隨著incrementor一同被存儲。

  • 閉包是引用類型
    無論您將函數/閉包賦值給一個常量還是變量,您實際上都是將常量/變量的值設置為對應函數/閉包的引用。

枚舉

枚舉簡單的說也是一種數據類型,只不過是這種數據類型只包含自定義的特定數據,它是一組有共同特性的數據的集合。
Swift 的枚舉類似于 Objective C 和 C 的結構,

  • 枚舉的功能為:
    它聲明在類中,可以通過實例化類來訪問它的值。
    枚舉也可以定義構造函數(initializers)來提供一個初始成員值;可以在原始的實現基礎上擴展它們的功能。
    可以遵守協議(protocols)來提供標準的功能。
  • 語法
    Swift 中使用 enum 關鍵詞來創建枚舉并且把它們的整個定義放在一對大括號內:
enum enumname {
   // 枚舉定義放在這里
}
  • 相關值
    以下實例中我們定義一個名為 Student 的枚舉類型,它可以是 Mark 的一個相關值(Int,Int,Int,Int),或者是 Name 的一個字符串類型(String)相關值。
enum Student{
    case Name(String)
    case Mark(Int,Int,Int)
}
var studDetails = Student.Name("Runoob")
var studMarks = Student.Mark(98,97,95)
switch studMarks {
case .Name(let studName):
    print("學生的名字是: \(studName)。")
case .Mark(let Mark1, let Mark2, let Mark3):
    print("學生的成績是: \(Mark1),\(Mark2),\(Mark3)。")
}
以上程序執行輸出結果為:
學生的成績是: 98,97,95。
  • 原始值
    原始值可以是字符串,字符,或者任何整型值或浮點型值。每個原始值在它的枚舉聲明中必須是唯一的。
    在原始值為整數的枚舉時,不需要顯式的為每一個成員賦值,Swift會自動為你賦值。
    例如,當使用整數作為原始值時,隱式賦值的值依次遞增1。如果第一個值沒有被賦初值,將會被自動置為0。
enum Month: Int {
    case January = 1, February, March, April, May, June, July, August, September, October, November, December
}
let yearMonth = Month.May.rawValue
print("數字月份為: \(yearMonth)。")
以上程序執行輸出結果為:
數字月份為: 5。

枚舉的定義方式如下,可以給枚舉類型的數據設置值也可以不設置值

/// 顏色類型枚舉
enum ColorType {
    case RGB
    case CMYK
    case HSB
}
let type: ColorType = .RGB
print(type)

/// 學科枚舉
enum Subject: String {
    case Chinese = "語文"
    case Math = "數學"
    case English = "英語"
}
let subjece: Subject = .Chinese
print(subjece)

注意: 和 C 和 Objective-C 不同,Swift 的枚舉成員在被創建時不會被賦予一個默認的整型值。

結構體

Swift 結構體是構建代碼所用的一種通用且靈活的構造體。
我們可以為結構體定義屬性(常量、變量)和添加方法,從而擴展結構體的功能。

  • 與 C 和 Objective C 不同的是:
    結構體不需要包含實現文件和接口。
    結構體允許我們創建一個單一文件,且系統會自動生成面向其它代碼的外部接口。
    結構體總是通過被復制的方式在代碼中傳遞,因此它的值是不可修改的。
  • 語法
我們通過關鍵字 struct 來定義結構體:
struct nameStruct { 
   Definition 1
   Definition 2
   ……
   Definition N
}

實例
我們定義一個名為 MarkStruct 的結構體 ,結構體的屬性為學生三個科目的分數,數據類型為 Int:

struct MarkStruct{
   var mark1: Int
   var mark2: Int
   var mark3: Int
}

我們可以通過結構體名來訪問結構體成員。
結構體實例化使用 let 關鍵字:

struct studentMarks {
   var mark1 = 100
   var mark2 = 78
   var mark3 = 98
}
let marks = studentMarks()
print("Mark1 是 \(marks.mark1)")
print("Mark2 是 \(marks.mark2)")
print("Mark3 是 \(marks.mark3)")
以上程序執行輸出結果為:
Mark1 是 100
Mark2 是 78
Mark3 是 98
  • 結構體應用
    在你的代碼中,你可以使用結構體來定義你的自定義數據類型。
    結構體實例總是通過值傳遞來定義你的自定義數據類型。
    按照通用的準則,當符合一條或多條以下條件時,請考慮構建結構體:
    • 結構體的主要目的是用來封裝少量相關簡單數據值。
    • 有理由預計一個結構體實例在賦值或傳遞時,封裝的數據將會被拷貝而不是被引用。
    • 任何在結構體中儲存的值類型屬性,也將會被拷貝,而不是被引用。
    • 結構體不需要去繼承另一個已存在類型的屬性或者行為。

Swift中的結構體和C語言類似,同時Swift的結構體還包括方法,這使得與類十分相似。不過結構體是不能繼承的,并且結構體是值類型的數據結構,而類是引用類型的數據結構。

  • 值類型:每次賦值都將創建副本,并把副本賦值給新的變量或常量,變量或常量存儲的是副本。
  • 引用類型:說白了,引用類型就是指針,不管賦值給多少變量或者常量,他們都指向同一個對象,變量和常量存儲的都是指向這個對象的引用,而不是副本。
struct Color {
  var R: Double = 0.0
  var G: Double = 0.0
  var B: Double = 0.0
  var Alpha: Double = 0.0

  func stringValue() -> String {
      let limit: Double = 255.0
      let rInt: Int = Int(self.R*limit)
      let gInt: Int = Int(self.G*limit)
      let bInt: Int = Int(self.B*limit)
      let alphaInt: Int = Int(self.Alpha*limit)

      let result: String = String.init(format: "%02X%02X%02X%02X", rInt, gInt, bInt, alphaInt)
      return result
  }
}
let red: Color = Color(R: 1.0, G: 0.0, B: 0.0, Alpha: 1)
print(red)
print(red.stringValue())

Swift 類是構建代碼所用的一種通用且靈活的構造體。
我們可以為類定義屬性(常量、變量)和方法。
與其他編程語言所不同的是,Swift 并不要求你為自定義類去創建獨立的接口和實現文件。你所要做的是在一個單一文件中定義一個類,系統會自動生成面向其它代碼的外部接口。

  • 類和結構體對比
    Swift 中類和結構體有很多共同點。共同處在于:
    定義屬性用于存儲值
    定義方法用于提供功能
    定義附屬腳本用于訪問值
    定義構造器用于生成初始化值
    通過擴展以增加默認實現的功能
    符合協議以對某類提供標準功能
    與結構體相比,類還有如下的附加功能:
    繼承允許一個類繼承另一個類的特征
    類型轉換允許在運行時檢查和解釋一個類實例的類型
    解構器允許一個類實例釋放任何其所被分配的資源
    引用計數允許對一個類的多次引用
  • 語法:
Class classname {
   Definition 1
   Definition 2
   ……
   Definition N
}

類定義

class student{
   var studname: String
   var mark: Int 
   var mark2: Int 
}

實例化類:

let studrecord = student()

實例

class MarksStruct {
    var mark: Int
    init(mark: Int) {
        self.mark = mark
    }
}
class studentMarks {
    var mark = 300
}
let marks = studentMarks()
print("成績為 \(marks.mark)")
以上程序執行輸出結果為:
成績為 300
  • 作為引用類型訪問類屬性
    類的屬性可以通過 . 來訪問。格式為:實例化類名.屬性名:
class studentMarks{
    var mark1 = 11
    var mark2 = 22
}
let marks = studentMarks()
print("mark1 is \(marks.mark1)")
  • 恒等運算符
    因為類是引用類型,有可能有多個常量和變量在后臺同時引用某一個類實例。
    為了能夠判定兩個常量或者變量是否引用同一個類實例,Swift 內建了兩個恒等運算符:
    • 恒等運算符 運算符為:===
      如果兩個常量或者變量引用同一個類實例則返回 true
    • 不恒等運算符 運算符為: !==
      如果兩個常量或者變量引用不同一個類實例則返回 true

屬性

Swift 屬性將值跟特定的類、結構或枚舉關聯。
屬性也可以直接用于類型本身,這種屬性稱為類型屬性。
另外,還可以定義屬性觀察器來監控屬性值的變化,以此來觸發一個自定義的操作。屬性觀察器可以添加到自己寫的存儲屬性上,也可以添加到從父類繼承的屬性上。
屬性可分為存儲屬性和計算屬性:
1.存儲屬性 存儲常量或變量作為實例的一部分 用于類和結構體
簡單來說,一個存儲屬性就是存儲在特定類或結構體的實例里的一個常量或變量。
存儲屬性可以是變量存儲屬性(用關鍵字var定義),也可以是常量存儲屬性(用關鍵字let定義)。

  • 可以在定義存儲屬性的時候指定默認值
  • 也可以在構造過程中設置或修改存儲屬性的值,甚至修改常量存儲屬性的值
  • 如果你定義的是一個常量存儲屬性,如果嘗試修改它就會報錯,如下所示:
struct Number
{
    var digits: Int
    let numbers = 3.1415
}
var n = Number(digits: 12345)
n.digits = 67
print("\(n.digits)")
print("\(n.numbers)")
n.numbers = 8.7
以上程序,執行會報錯,錯誤如下所示:
error: cannot assign to property: 'numbers' is a 'let' constant
n.numbers = 8.7
  • 延遲存儲屬性
    延遲存儲屬性是指當第一次被調用的時候才會計算其初始值的屬性。
    在屬性聲明前使用 lazy 來標示一個延遲存儲屬性。
    • 注意:
      必須將延遲存儲屬性聲明成變量(使用var關鍵字),因為屬性的值在實例構造完成之前可能無法得到。而常量屬性在構造過程完成之前必須要有初始值,因此無法聲明成延遲屬性。
    • 延遲存儲屬性一般用于:
      延遲對象的創建。
      當屬性的值依賴于其他未知類
      實例
class sample {
    lazy var no = number() // `var` 關鍵字是必須的
}
class number {
    var name = "Runoob Swift 教程"
}
var firstsample = sample()
print(firstsample.no.name)
以上程序執行輸出結果為:
Runoob Swift 教程

2.計算屬性 計算(而不是存儲)一個值 用于類、結構體和枚舉
計算屬性不直接存儲值,而是提供一個 getter 來獲取值,一個可選的 setter 來間接設置其他屬性或變量的值。

  • 只讀計算屬性
    只有 getter 沒有 setter 的計算屬性就是只讀計算屬性。
    只讀計算屬性總是返回一個值,可以通過點(.)運算符訪問,但不能設置新的值。
    注意:
    必須使用var關鍵字定義計算屬性,包括只讀計算屬性,因為它們的值不是固定的。let關鍵字只用來聲明常量屬性,表示初始化后再也無法修改的值。

3.屬性觀察器
屬性觀察器監控和響應屬性值的變化,每次屬性被設置值的時候都會調用屬性觀察器,甚至新的值和現在的值相同的時候也不例外。
可以為除了延遲存儲屬性之外的其他存儲屬性添加屬性觀察器,也可以通過重載屬性的方式為繼承的屬性(包括存儲屬性和計算屬性)添加屬性觀察器。
注意:
不需要為無法重載的計算屬性添加屬性觀察器,因為可以通過 setter 直接監控和響應值的變化。

  • 可以為屬性添加如下的一個或全部觀察器:
    willSet在設置新的值之前調用
    didSet在新的值被設置之后立即調用
    willSet和didSet觀察器在屬性初始化過程中不會被調用
    實例
class Samplepgm {
    var counter: Int = 0{
        willSet(newTotal){
            print("計數器: \(newTotal)")
        }
        didSet{
            if counter > oldValue {
                print("新增數 \(counter - oldValue)")
            }
        }
    }
}
let NewCounter = Samplepgm()
NewCounter.counter = 100
NewCounter.counter = 800
以上程序執行輸出結果為:
計數器: 100
新增數 100
計數器: 800
新增數 700

4.實例化變量
如果您有過 Objective-C 經驗,應該知道Objective-C 為類實例存儲值和引用提供兩種方法。對于屬性來說,也可以使用實例變量作為屬性值的后端存儲。
Swift 編程語言中把這些理論統一用屬性來實現。Swift 中的屬性沒有對應的實例變量,屬性的后端存儲也無法直接訪問。這就避免了不同場景下訪問方式的困擾,同時也將屬性的定義簡化成一個語句。
一個類型中屬性的全部信息——包括命名、類型和內存管理特征——都在唯一一個地方(類型定義中)定義。

5.全局變量和局部變量
計算屬性和屬性觀察器所描述的模式也可以用于全局變量和局部變量。

  • 局部變量 在函數、方法或閉包內部定義的變量。 用于存儲和檢索值。 存儲屬性用于獲取和設置值。也用于計算屬性。

  • 全局變量 函數、方法、閉包或任何類型之外定義的變量。 用于存儲和檢索值。 存儲屬性用于獲取和設置值。 也用于計算屬性。

6.類型屬性
類型屬性是作為類型定義的一部分寫在類型最外層的花括號({})內。
使用關鍵字 static 來定義值類型的類型屬性,關鍵字 class 來為類定義類型屬性。

struct Structname {
   static var storedTypeProperty = " "
   static var computedTypeProperty: Int {
      // 這里返回一個 Int 值
   }
}

enum Enumname {
   static var storedTypeProperty = " "
   static var computedTypeProperty: Int {
      // 這里返回一個 Int 值
   }
}

class Classname {
   class var computedTypeProperty: Int {
      // 這里返回一個 Int 值
   }
}

注意:例子中的計算型類型屬性是只讀的,但也可以定義可讀可寫的計算型類型屬性,跟實例計算屬性的語法類似。

  • 獲取和設置類型屬性的值
    類似于實例的屬性,類型屬性的訪問也是通過點運算符(.)來進行。但是,類型屬性是通過類型本身來獲取和設置,而不是通過實例。

方法

Swift 方法是與某些特定類型相關聯的函數
在 Objective-C 中,類是唯一能定義方法的類型。但在 Swift 中,你不僅能選擇是否要定義一個類/結構體/枚舉,還能靈活的在你創建的類型(類/結構體/枚舉)上定義方法。

  • 實例方法
    在 Swift 語言中,實例方法是屬于某個特定類、結構體或者枚舉類型實例的方法。
    實例方法提供以下方法:
    可以訪問和修改實例屬性
    提供與實例目的相關的功能
    實例方法要寫在它所屬的類型的前后大括號({})之間。
    實例方法能夠隱式訪問它所屬類型的所有的其他實例方法和屬性。
    實例方法只能被它所屬的類的某個特定實例調用。
    實例方法不能脫離于現存的實例而被調用。
    語法
func funcname(Parameters) -> returntype
{
    Statement1
    Statement2
    ……
    Statement N
    return parameters
}

實例

class Counter {
    var count = 0
    func increment() {
        count += 1
    }
    func incrementBy(amount: Int) {
        count += amount
    }
    func reset() {
        count = 0
    }
}
// 初始計數值是0
let counter = Counter()
// 計數值現在是1
counter.increment()
// 計數值現在是6
counter.incrementBy(amount: 5)
print(counter.count)
// 計數值現在是0
counter.reset()
print(counter.count)
以上程序執行輸出結果為:
6
0

Counter類定義了三個實例方法:

  • increment 讓計數器按 1 遞增;

  • incrementBy(amount: Int) 讓計數器按一個指定的整數值遞增;

  • reset 將計數器重置為0。

  • 方法的局部參數名稱和外部參數名稱
    Swift 函數參數可以同時有一個局部名稱(在函數體內部使用)和一個外部名稱(在調用函數時使用
    Swift 中的方法和 Objective-C 中的方法極其相似。像在 Objective-C 中一樣,Swift 中方法的名稱通常用一個介詞指向方法的第一個參數,比如:with,for,by等等。
    Swift 默認僅給方法的第一個參數名稱一個局部參數名稱;默認同時給第二個和后續的參數名稱為全局參數名稱。

  • 是否提供外部名稱設置
    我們強制在第一個參數添加外部名稱把這個局部名稱當作外部名稱使用(Swift 2.0前是使用 # 號)。
    相反,我們呢也可以使用下劃線(_)設置第二個及后續的參數不提供一個外部名稱。

class multiplication {
    var count: Int = 0
    func incrementBy(first no1: Int, no2: Int) {
        count = no1 * no2
        print(count)
    }
}
let counter = multiplication()
counter.incrementBy(first: 800, no2: 3)
counter.incrementBy(first: 100, no2: 5)
  • self 屬性
    類型的每一個實例都有一個隱含屬性叫做self,self 完全等同于該實例本身。
    你可以在一個實例的實例方法中使用這個隱含的self屬性來引用當前實例。
  • 在實例方法中修改值類型
    Swift 語言中結構體和枚舉是值類型。一般情況下,值類型的屬性不能在它的實例方法中被修改。
    但是,如果你確實需要在某個具體的方法中修改結構體或者枚舉的屬性,你可以選擇變異(mutating)這個方法,然后方法就可以從方法內部改變它的屬性;并且它做的任何改變在方法結束時還會保留在原始結構中。
    方法還可以給它隱含的self屬性賦值一個全新的實例,這個新實例在方法結束后將替換原來的實例。
  • 在可變方法中給 self 賦值
    可變方法能夠賦給隱含屬性 self 一個全新的實例。
struct area {
    var length = 1
    var breadth = 1
    func area() -> Int {
        return length * breadth
    }
    mutating func scaleBy(res: Int) {
        self.length *= res
        self.breadth *= res
        print(length)
        print(breadth)
    }
}
var val = area(length: 3, breadth: 5)
val.scaleBy(res: 13)
以上程序執行輸出結果為:39    65
  • 類型方法
    實例方法是被類型的某個實例調用的方法,你也可以定義類型本身調用的方法,這種方法就叫做類型方法。
    聲明結構體和枚舉的類型方法,在方法的func關鍵字之前加上關鍵字static。類可能會用關鍵字class來允許子類重寫父類的實現方法。
    類型方法和實例方法一樣用點號(.)語法調用。
class Math
{
    class func abs(number: Int) -> Int
    {
        if number < 0
        {
            return (-number)
        }
        else
        {
            return number
        }
    }
}
struct absno
{
    static func abs(number: Int) -> Int
    {
        if number < 0
        {
            return (-number)
        }
        else
        {
            return number
        }
    }
}
let no = Math.abs(number: -35)
let num = absno.abs(number: -5)
print(no)
print(num)
以上程序執行輸出結果為:
35
5
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,443評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,530評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,407評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,981評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,759評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,204評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,263評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,415評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,955評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,650評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,892評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,675評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,967評論 2 374

推薦閱讀更多精彩內容