Swift 語言入門(三)控制流程 << 前情 今天介紹 Swift 常用的函式,這類的資料不多,大多由開發者從 Xcode 的自動完成去發掘,網路上有人整理出來 74個官方有寫出來跟沒寫出來的標準函式 我們今天來介紹一些常用的型態,以及這些型態有哪些函式可以使用。 文章會介紹 String, Array, Dictionary 函式使用,Numeric Types(Boolean, Integer, Float),Protocols (Equatable, Comparable, Printable) 以及一些內建的演算法函式,並且稍微帶一下 Optional, Enum, Generic 等觀念。 型態
- String
- Array
- Dictionary
- Numeric Types
String
字串(String)是由一連串的字元(Characters)所組成,我們來看看字串、字元有哪些函式可以運用。 建立字串
- init()
- init(count:, repeatedValue:)
init() 初始化一個空的字串。 宣告
使用
1
2
3
4
|
let emptyString = String()
let emptyString2 =
""
|
init(count:, repeatedValue:) 建構一個字串,第一個傳入的參數為重複次數 ,第二個為重複的字元。 宣告
1
|
init(count sz: Int, repeatedValue c: Character)
|
使用
1
2
|
let string = String(count:
5
, repeatedValue: Character(
"a"
))
|
字串搜尋
- var isEmpty { get }
- hasPrefix(_
-> Bool - hasSuffix(_
-> Bool var isEmpty { get } isEmpty 用來測試字串是否為空值,get 表示 唯讀(read-only),所以此函式只能取值(get)無法寫入(set)。 宣告
1
|
var isEmpty: Bool { get }
|
使用
1
2
3
4
5
6
7
|
var string =
"Hello, world!"
let firstCheck = string.isEmpty
string =
""
let secondCheck = string.isEmpty
|
hasPrefix(_ -> Bool hasPrefix 是 String 的函式,用來判斷字串的開頭是否與接收物件(receiver)相同。 宣告
使用
1
2
3
4
5
6
|
let string =
"Hello, world"
let firstCheck = string.hasPrefix(
"Hello"
)
let secondCheck = string.hasPrefix(
"hello"
)
|
hasSuffix(_ -> Bool hasSuffix 與 hasPrefix 類似,字面上的意思則是字尾是否相同。 宣告
1
|
func hasSuffix(suffix: String) -> Bool
|
使用
1
2
3
4
5
6
|
let string =
"Hello, world"
let firstCheck = string.hasSuffix(
"world"
)
let secondCheck = string.hasSuffix(
"World"
)
|
字串轉型
toInt() -> Int? 將字串轉為 Int 型態,但回傳的結果是 Optional Integer。
Optional 是一個 Enum ,定義兩種型態 None & Some(T) ,None 代表空值,Some帶著某種任意的型態,保存著應該呈現的數值,例如本次範例所要表達的 Int? ,如果回傳的結果是正確的,Some就會帶著 Int 回傳結果。
Enum 中文叫做 列舉,是 Enumerations 的縮寫,在程式當中用來定義一組相關的數值,例如:方位,可定義出 東、南、西、北,Optional 則 定義 None、Some。Enum 在 Swift 語言當中有許多強化的功能,後續的章節我們再來介紹。
宣告
使用
1
2
3
4
5
6
7
8
|
let string =
"42"
if
( let number = string.toInt() ) {
println(
"字串轉為數字: \(number)"
)
}
else
{
println(
"無法轉換!"
)
}
|
運算元
以前在 Objective-C 字串的串接不是那麼的方便與直覺,Swift 有了字串運算元的加持,我們可以用更直覺的方式,來做字串相加。 + 字串串接,在這裡必須先跟大家說明 Swift 的演進,以前是可以透過加號運算元(+)串接字元,自從 Xcode6 beta6 就不再允許這樣做,Characters 與 Strings 相加必須改用 String(c1) ,字元必須做一個轉型的動作。 宣告
1
2
3
4
5
6
|
func + (lhs: String, rhs: String) -> String
func + (lhs: Character, rhs: Character) -> String
func + (lhs: String, rhs: Character) -> String
func + (lhs: Character, rhs: String) -> String
|
使用
1
2
|
let combination =
"Hello "
+
"world"
|
字元與字串相加必須轉為字串!
1
2
3
4
5
6
|
let exclamationPoint: Character =
"!"
let charCombo = combination + String(exclamationPoint)
let extremeCombo = String(exclamationPoint) + charCombo
|
字元相加後會轉為字串
1
2
3
4
|
let first: Character =
"a"
let second: Character =
"b"
let result = first + second
|
+= 字串的附加運算元。 宣告
1
2
3
4
|
@assignment
func += (inout lhs: String, rhs: String)
@assignment
func += (inout lhs: String, rhs: Character)
|
使用
1
2
3
|
var string =
"Hello "
string +=
"world!"
|
字元必須轉型字串方能與字串相加。
1
2
3
|
var character: Character =
"?"
string += String(character)
|
常數無法附加字串。所以此處 let string 要改為 var string。
1
2
3
|
let string =
"Hello "
string +=
"world!"
|
== 判斷字串內容是否相等。 宣告
1
|
func == (lhs: String, rhs: String) -> Bool
|
使用
1
2
3
4
|
let string1 =
"Hello world!"
let string2 =
"Hello"
+
" "
+
"world"
+
"!"
let result = string1 == string2
|
< 字串的比較運算,比較運算元會把字串轉換成可以比較的數字,使字串與字串、字元與字元可相互比較。 宣告
1
2
|
func < (lhs: String.UnicodeScalarView.Index, rhs: String.UnicodeScalarView.Index) -> Bool
func < (lhs: Character, rhs: Character) -> Bool
|
使用 字串與字串比較。
1
2
3
4
5
6
7
8
|
let string1 =
"Number 3"
let string2 =
"Number 2"
let result1 = string1 < string2
let result2 = string2 < string1
|
字串與字串比較。
1
2
3
4
5
6
7
|
let string3 =
"aa"
let string4 =
"bb"
string3 < string4
string4 < string3
|
字元與字元比較。
1
2
3
4
5
6
7
|
let c1 =
"a"
let c2 =
"b"
c1 < c2
c2 < c1
|
Array
- 建立陣列
- 存取陣列元素
- 增加、移除陣列元素
- 陣列搜尋
- 陣列的演算法
- 運算元
陣列是一個儲存連續資料的型態,他們必須存放相同型態(T)的元素。
<T> 此處稱作泛型(Generic),此處的泛型用來定義陣列裡的元素必須相同,其實泛型的另個用途在於程式碼靈活地重複使用。例如:我們定義一個型態為 Stack<T>,就不需要 Int 也寫一個 IntStack,String 也寫一個 StringStack,運用泛型就可重複利用程式碼。
建立陣列
- init()
- init(count:, repeatedValue:)
init() 創建一個空陣列。 宣告
使用
1
2
3
4
|
var emptyArray = Array<Int>()
var equivalentEmptyArray = [Int]()
|
init(count:, repeatedValue:) 創建一個陣列相同元素內容的陣列,第一個參數代表 重複的數量,第二個參數代表元素的數值, 宣告
1
|
init(count: Int, repeatedValue: T)
|
使用
1
2
3
4
5
|
let numericArray = Array(count:
3
, repeatedValue:
42
)
let stringArray = Array(count:
2
, repeatedValue:
"Hello"
)
|
存取陣列元素
- subscript(Int) -> T { get set }
- subscript(Range) -> Slice
subscript 叫做下標語法,接收物件(receiver) 可以用中括號呼叫函式。
subscript(Int) -> T { get set } 透過中括號與Index( Array[index] ),可取得陣列的特定元素。 宣告
1
|
subscript(index: Int) -> T { get { } nonmutating set { } }
|
使用
1
2
3
4
5
|
var subscriptableArray = [
"zero"
,
"one"
,
"two"
,
"three"
] subscriptableArray[
0
]
let three = subscriptableArray[
3
]
|
如果陣列宣告為 var,我們將可變動其內部的數值。 所以陣列的下標語法,不僅可以 get 也能 set。
1
2
|
subscriptableArray[
0
] =
"nothing"
subscriptableArray[
3
] =
"three items"
|
注意陣列範圍。
1
2
|
subscriptableArray[
4
] =
"new item"
|
注意常數陣列無法更動。
1
2
|
let constantArray = [
"zero"
,
"one"
,
"two"
,
"three"
] constantArray[
0
] =
"nothing"
|
subscript(Range) -> Slice 使用中括號下標語法傳入 Range 並且為 Int 型態,將符合的元素回傳為 Slice 。 宣告
1
|
subscript(subRange: Range<Int>) -> Slice<T> { get { } set { } }
|
使用 取得 1到3 包含3的元素,陣列元素從 0 開始算起 ,所以結果是:["one", "two", "three"]。
1
2
3
|
var subscriptableArray = [
"zero"
,
"one"
,
"two"
,
"three"
]
let subRange = subscriptableArray[
1
...
3
]
|
將 1到2 元素,取代為 ["oneone", "twotwo"] 此二元素。
1
2
|
subscriptableArray[
1
...
2
] = [
"oneone"
,
"twotwo"
]
|
將 1到2 元素,取代為 空陣列。
1
2
|
subscriptableArray[
1
...
2
] = []
|
注意陣列範圍。
1
2
|
subscriptableArray[
4
...
5
] = [
"four"
,
"five"
]
|
注意陣列是否為常數。
1
2
|
let constantArray = [
"zero"
,
"one"
,
"two"
,
"three"
] constantArray[
1
...
2
] = []
|
增加、移除陣列元素
- append()
- insert(_ :, atIndex:)
- removeAtIndex() -> T
- removeLast() -> T
- removeAll(keepCapacity: = false)
- reserveCapacity()
append() 附加一個元素到一個已經存在的陣列。 宣告
1
|
mutating func append(newElement: T)
|
使用
1
2
3
4
5
6
|
var array = [
0
,
1
]
array.append(
2
)
array.append(
3
)
|
相同的,您無法附加一個元素,到一個常數陣列。
1
2
3
|
let constantArray = [
0
,
1
]
constantArray.append(
2
)
|
insert(_ :, atIndex:) 插入一個元素,到陣列的特定位置。注意插入不是取代! 宣告
1
|
mutating func insert(newElement: T, atIndex: Int)
|
使用 在陣列的最前面插入 0。
1
2
3
|
var array = [
1
,
2
,
3
]
array.insert(
0
, atIndex:
0
)
|
同樣的,不能超出陣列範圍。
1
2
|
array.insert(
6
, atIndex:
6
)
|
一樣無法針對常數陣列做插入的動作。
1
2
3
|
let constantArray = [
1
,
2
,
3
]
constantArray.insert(
0
, atIndex:
0
)
|
removeAtIndex() -> T 移除特定元素。 宣告
1
|
mutating func removeAtIndex(index: Int) -> T
|
使用 移除陣列的第一個元素。
1
2
3
4
|
var array = [
0
,
1
,
2
,
3
]
let removed = array.removeAtIndex(
0
)
|
同樣不可超出陣列範圍。
常數陣列不可變動。
1
2
3
|
let constantArray = [
0
,
1
,
2
] constantArray.removeAtIndex(
0
)
'removeAtIndex'
|
removeLast() -> T 移除陣列最後一個元素,並且回傳它。 宣告
1
|
mutating func removeLast() -> T
|
使用
1
2
3
4
|
var array = [
1
,
2
,
3
]
let removed = array.removeLast()
|
呼叫 removeLast 函式,陣列內必須至少有一個元素在裡面,否則將會出錯。
1
2
3
|
var emptyArray = [Int]()
let tryToRemove = emptyArray.removeLast()
|
常數陣列不可修改。
1
2
3
|
let constantArray = [
1
,
2
]
constantArray.removeLast()
|
removeAll(keepCapacity: = false) 移除陣列所有元素,預設為清空 storage buffer,除非特別指定keepCapacity。 宣告
1
|
mutating func removeAll(keepCapacity: Bool =
false
)
|
使用
1
2
3
4
|
var array = [
0
,
1
,
2
,
3
]
array.removeAll()
let count = array.count
|
常數陣列無法更動。
1
2
3
|
let constantArray = [
1
,
2
]
constantArray.removeAll()
|
reserveCapacity() 設定陣列底層的儲存空間。
Array 在記憶體所展示的是一段連續記憶體空間,如果元素超過了此設定大小的空間,則必須重新配置空間來存放元素。
宣告
1
|
mutating func reserveCapacity(minimumCapacity: Int)
|
使用
1
2
3
|
var array = [
0
,
1
,
2
,
3
]
array.reserveCapacity(
10
)
|
陣列搜尋
- var count { get }
- var isEmpty { get }
- var capacity { get }
var count { get } 回傳總共有幾個元素。 宣告
使用
1
2
3
4
5
6
7
|
var array = [
"zero"
,
"one"
,
"two"
]
let firstCount = array.count
array +=
"three"
let secondCount = array.count
|
var isEmpty { get } isEmpty 用來測試陣列是否為空陣列,get 表示 唯讀(read-only),所以此函式只能取值(get)無法寫入(set)。 宣告
1
|
var isEmpty: Bool { get }
|
使用
1
2
3
4
5
6
7
|
var array = [
"zero"
,
"one"
,
"two"
,
"three"
]
let firstCheck = array.isEmpty
array.removeAll()
let secondCheck = array.isEmpty
|
var capacity { get } 顯示目前陣列所配置的空間大小為多少,get 表示 唯讀(read-only)。 宣告
1
|
var capacity: Int { get }
|
使用
1
2
3
|
var array = [
0
,
1
,
2
,
3
]
array.capacity
|
陣列的演算法
- sort(_
 - sorted(_
-> Array<T> - reverse() -> Array<T>
- filter(_
-> Array<T> - map<U>(_
-> Array<U> - reduce<U>(_:, combine: (U, T)->U) -> U
sort(_  Swift 內建一些常用的演算法,像是 sort,我們可以透過 Closure 去比對,並且排序。
Closure 像是 Objective-C 裡頭的 Block 概念或稱之為 lambda 函式。Closure 在 Swift 語言裡頭也是扮演很重要的角色。之後的教學文章將會特別說明。
宣告
1
|
mutating func sort(isOrderedBefore: (T, T) -> Bool)
|
使用 sort 函式只有一個參數,但這個參數比較特別,它是 Closure ,在Closure 內執行的結果必須回傳 Bool 值,isOrderedBefore 表示如果回傳為 true,將排在前面,反之往後排序。
此範例出現神奇的變數,$0, $1,稱作 Shorthand Argument Names ,這個意思是參數名稱縮寫,從 $0 開始代表第一個參數,$1 第二個,依此類推。
在此 sort 函式的用法應該為 array.sort( { $0 < $1 } ) ,括號為呼叫函式,括號內為 Closure 參數,但此處使用的方式叫做 Trailing Closures ,若 Closure 為函式最後一個參數時,可提出括號外面撰寫部分程式,若只有一個 Closure 參數時,甚至不需要括號,如下範例,可讓程式碼更簡潔易讀。
1
2
3
4
5
6
|
var array = [
3
,
2
,
5
,
1
,
4
]
array.sort { $
0
< $
1
}
array.sort { $
1
< $
0
}
|
sorted(_ -> Array<T> 跟 sort 函式類似,不過 sorted 會將排序結果,組成陣列回傳。 宣告
1
|
func sorted(isOrderedBefore: (T, T) -> Bool) -> Array<T>
|
使用
1
2
3
4
5
6
|
let array = [
3
,
2
,
5
,
1
,
4
]
let sortedArray = array.sorted { $
0
< $
1
}
let descendingArray = array.sorted { $
1
< $
0
}
|
reverse() -> Array<T> 回傳一個反向的陣列。 宣告
1
|
func reverse() -> Array<T>
|
使用
1
2
3
|
let array = [
2
,
0
,
1
,
4
]
let reversedArray = array.reverse()
|
filter(_ -> Array<T> 尋訪每個陣列內的元素,執行傳入的 Closure 回傳 ture 時,加入回傳結果的陣列。 宣告
1
|
func filter(includeElement: (T) -> Bool) -> Array<T>
|
使用 尋訪每個元素,留下二的倍數。
1
2
3
|
let array = [
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
]
let filteredArray = array.filter { $
0
%
2
==
0
}
|
map<U>(_ -> Array<U> 尋訪每個元素,執行傳入的 Closure 加以處理元素後,加入回傳的陣列當中。 宣告
1
|
func map<U>(transform: (T) -> U) -> Array<U>
|
使用 map 可將每個 陣列的元素加以處理,將每個元素乘上倍數,或將元素組成字串。
1
2
3
4
5
6
|
let array = [
0
,
1
,
2
,
3
]
let multipliedArray = array.map { $
0
*
2
}
let describedArray = array.map {
"Number: \($0)"
}
|
reduce<U>(_:, combine: (U, T)->U) -> U 尋訪每個元素,並將該尋訪的元素,成為下個元素的處理參數,又稱之為 fold 。 宣告
1
|
func reduce<U>(initial: U, combine: (U, T) -> U) -> U
|
使用 reduce 的用法,需給它一個初始值,接著在尋訪每個元素時,與每個元素計算結合為一個元素,以遞迴的方式,不斷的呼叫第二個參數,Closure 運算。 舉個例子:從 1 加到 5。
1
2
3
4
5
6
|
let array = [
1
,
2
,
3
,
4
,
5
]
let addResult = array.reduce(
0
) { $
0
+ $
1
}
let multiplyResult = array.reduce(
1
) { $
0
* $
1
}
|
第一個 array 相加 的 reduce,將它拆解後,初始值我們給0,所以第一步將是 初始值 0 + array第一個元素 1 ,相加結果是 1,第二部是將 第一步算得的結果 1 + array第二個元素 2 ,以此類推。
相乘的例子也是一樣,初始值我們給1,所以第一步將是 初始值 1 * array第一個元素 1 ,相乘結果是 1,第二部是將 第一步算得的結果 1 * array第二個元素 2 ,以此類推。
陣列運算元
+= 陣列的附加,原本在 Xcode6 beta5 之前,可以任意附加元素或是陣列,但之後修改為,必須要是陣列與陣列才能附加。如同宣告方式所定義: 宣告
1
2
3
4
|
func +=<T, C : CollectionType where T == T>(inout lhs: _ContiguousArrayBuffer<T>, rhs: C)
@assignment
func += <U>(inout lhs: Array<T>, rhs: U)
|
使用 此處用法注意 += 兩端皆需為陣列型態。
1
2
3
4
5
6
|
var array = [
0
,
1
,
2
]
array += [
3
]
array += [
4
,
5
,
6
]
|
Dictionary
字典也是個必須遵守泛型(Generic)的一種形態,顧名思義類似字典,儲存著鍵值(key)與數值(value),例如:apple 對應到 蘋果,假設 apple 為鍵值,對應到的數值結果就是 蘋果。 建立字典
- init(minimumCapacity: = 2)
init(minimumCapacity: = 2) 創建字典,最小記憶體空間預設值為2。 宣告
1
|
init(minimumCapacity: Int =
2
)
|
使用
1
2
|
var emptyDictionary = Dictionary<String, Int>()
|
這兩種宣告方式的結果是一樣的。
1
|
var equivalentEmptyDictionary = [String: Int]()
|
存取、修改字典內容
- subscript (key: Key) -> Value?
- updateValue(_:, forKey:) -> Value?
- removeValueForKey(_:) -> Value?
- removeAll(keepCapacity: = false)
subscript (key: Key) -> Value? 下標語法subscript 在陣列與字典都很常用,而且直覺,許多語言大多都是以這樣的方式存取。 宣告
1
|
subscript (key: Key) -> Value?
|
使用
1
2
3
|
var dictionary = [
"one"
:
1
,
"two"
:
2
,
"three"
:
3
]
let value = dictionary[
"two"
]
|
這邊用到的是一種 Optional 特殊寫法,叫做 Optional Binding ,訣竅是 if let ,若 Optional 有值 會直接賦予到變數當中,若沒有值,則為 false 條件不成立。這樣我們就不用猜測變數究竟會是什麼型態,而寫出許多判斷式,我們稱之為防禦性編程(Defensive Programming),減少這類的程式碼,問題與臭蟲相對較少,開發者也能更專注在資料流與商業邏輯。
1
2
3
4
|
if
let unwrappedValue = dictionary[
"three"
] {
println(
"字典透過鍵值 \"three\" 取出的值是 \(unwrappedValue)"
)
}
|
能用下標語法取值,同樣也能用來更新數值。
1
2
3
4
5
6
7
8
|
dictionary[
"three"
] =
33
dictionary[
"four"
] =
4
dictionary[
"three"
] = nil
|
若字典定義為常數,修改的下標語法將無法使用!
1
2
3
4
|
let constantDictionary = [
"one"
:
1
,
"two"
:
2
,
"three"
:
3
]
constantDictionary[
"four"
] =
4
arguments
|
updateValue(_:, forKey:) -> Value? 插入或更新字典數值,第一個參數為更新的數值,第二個參數為鍵值,並回傳將被取代的數值。 宣告
1
|
mutating func updateValue(value: Value, forKey key: Key) -> Value?
|
使用
1
2
3
|
var dictionary = [
"one"
:
1
,
"two"
:
2
,
"three"
:
3
]
let previousValue = dictionary.updateValue(
22
, forKey:
"two"
)
|
若用 Optional Binding 方式表達,則範例如下:
1
2
3
4
5
6
7
|
if
let unwrappedPreviousValue = dictionary.updateValue(
33
, forKey:
"three"
) {
println(
"取代的數值為 \(unwrappedPreviousValue)"
)
}
else
{
println(
"這是一個新的 key-value "
)
}
|
removeValueForKey(_:) -> Value? 傳入鍵值,移除該組 key-value,並且回傳被移除的數值。 宣告
1
|
mutating func removeValueForKey(key: Key) -> Value?
|
使用
1
2
3
|
var dictionary = [
"one"
:
1
,
"two"
:
2
,
"three"
:
3
]
let previousValue = dictionary.removeValueForKey(
"two"
)
|
removeValueForKey 將回傳被移除的數值。
1
2
3
4
5
6
7
|

if
let unwrappedPreviousValue = dictionary.removeValueForKey(
"three"
) {
println(
"移除的數值為 \(unwrappedPreviousValue)"
)
}
else
{
println(
"找不到可以刪除的值"
)
}
|
removeAll(keepCapacity: = false) 移除字典內所有 key-value 數值,預設為清空 storage buffer,除非特別指定keepCapacity。 宣告
1
|
mutating func removeAll(keepCapacity: Bool =
default
)
|
使用
1
2
|
var dictionary = [
"one"
:
1
,
"two"
:
2
,
"three"
:
3
] dictionary.removeAll()
|
字典搜尋
- var count { get }
- var keys { get }
- var values { get }
var count { get } 將回傳 字典共有多少組 key-value。 宣告
使用
1
2
3
|
var dictionary = [
"one"
:
1
,
"two"
:
2
,
"three"
:
3
]
let elementCount = dictionary.count
|
var keys { get } 這是個唯讀的函式,回傳所有鍵值,並且為 CollectionType。 宣告
1
|
var keys: LazyBidirectionalCollection<MapCollectionView<[Key : Value], Key>> { get }
|
使用 使用 for-in 迴圈尋訪每個鍵值,並且印出來。
1
2
3
4
5
6
7
8
|
var dictionary = [
"one"
:
1
,
"two"
:
2
,
"three"
:
3
]
for
key in dictionary.keys {
println(key)
}
|
轉為 Array 即可使用 Array 的函式。
1
2
|
let array = Array(dictionary.keys)
|
var values { get } 回傳字典內所有數值,這是個未排序的數值 collection。 宣告
1
|
var values: LazyBidirectionalCollection<MapCollectionView<[Key : Value], Value>> { get }
|
使用
1
2
3
4
5
6
7
8
|
var dictionary = [
"one"
:
1
,
"two"
:
2
,
"three"
:
3
]
for
value in dictionary.values {
println(
"數值: \(value)"
)
}
|
轉為 Array 即可使用 Array 的函式。
1
2
|
let array = Array(dictionary.values)
|
字典的運算元
== 判斷字典內容是否相等。 宣告
1
|
func ==<Key : Equatable, Value : Equatable>(lhs: [Key : Value], rhs: [Key : Value]) -> Bool
|
使用 定義一個 dictionary1 的字典常數,然後跟一個 dictionary2 的字典比較,內容相同為 true。
1
2
3
4
5
|
let dictionary1 = [
"one"
:
1
,
"two"
:
2
]
var dictionary2 = [
"one"
:
1
]
dictionary2[
"two"
] =
2
let result = dictionary1 == dictionary2
|
!= 用法與== 相同,只不過意思相反,用來比較字典內容是否不相同。 宣告
1
|
func !=<Key : Equatable, Value : Equatable>(lhs: [Key : Value], rhs: [Key : Value]) -> Bool
|
使用 因為 dictionary1 與 dictionary2 內容完全不同,所以結果為 true。
1
2
3
4
|
let dictionary1 = [
"one"
:
1
,
"two"
:
2
]
let dictionary2 = [
"one"
:
1
]
let result = dictionary1 != dictionary2
|
Numeric Types
- Boolean Types
- Integer Types
- Floating Point Types
Swift 標準函式使用數值型態來表示與儲存布林值、數字、浮點數。 Boolean Types Swift 的布林型態叫做 Bool,分別只有兩種內容 true 與 false,預設為 false。 Integer Types Swift 的主要數字型態 Int 在 32bit 的平台,它的大小就會是 32bit,在64bit的平台就會是64bit。 下表為 Int 數值的範圍:
型別 | 最小值 | 3最大值 |
---|
Int8 | -128 | 127 | Int16 | -32,768 | 32,767 | Int32 | -2,147,483,648 | 2,147,483,647 | Int64 | -9,223,372,036,854,775,808 | 9,223,372,036,854,775,807 | UInt8 | 0 | 255 | UInt16 | 0 | 65,535 | UInt32 | 0 | 4,294,967,295 | UInt64 | 0 | 18,446,744,073,709,551,615 | Floating Point Types 在 Swift 主要的浮點數型態為 Double,使用的是 64bit的精準度,當然也可以使用32bit精準度的 Float。 Protocols
- Equatable
- Comparable
- Printable
我們將介紹 Swift 語言裡面,最基礎常見的三個Protocols (協定)。 Equatable 判斷是否相等 == 宣告
1
|
func == (lhs: Self, rhs: Self) -> Bool
|
使用 底下定義一個 struct 叫 MyStruct,遵從 Equatable 協定,我們必須在全域環境底下實作 == function,並且回傳布林值 true 代表相等,false 則不相等。 我們實作== function,讓它判斷MyStruct 的name 相同時,代表相等。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
struct MyStruct: Equatable {
var name =
"不具名"
}
func == (lhs: MyStruct, rhs: MyStruct) -> Bool {
return
lhs.name == rhs.name
}
let value1 = MyStruct()
var value2 = MyStruct()
let firstCheck = value1 == value2
value2.name =
"路人甲"
let secondCheck = value1 == value2
|
Comparable 比較值 < Comparable 協定 讓兩個值可以比較大或小。 而最少必須實作< 與== ,為什麼?我們來看原始碼。 Comparable 繼承兩個協定 _Comparable 、Equatable ,Equatable剛剛說明過了,我們來看另外一個 _Comparable,是的就是< ,當實作完< 與== ,您將自動獲得 <= 、>= 、> 這三個比較運算元! 宣告
1
2
3
4
5
6
7
8
9
|
protocol Comparable : _Comparable, Equatable {
func <=(lhs: Self, rhs: Self) -> Bool
func >=(lhs: Self, rhs: Self) -> Bool
func >(lhs: Self, rhs: Self) -> Bool
}
protocol _Comparable {
func <(lhs: Self, rhs: Self) -> Bool
}
|
使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
struct MyStruct: Comparable {
var name =
"A"
}
func < (lhs: MyStruct, rhs: MyStruct) -> Bool {
return
lhs.name < rhs.name
}
func == (lhs: MyStruct, rhs: MyStruct) -> Bool {
return
lhs.name == rhs.name
}
let value1 = MyStruct()
var value2 = MyStruct()
let check1 = value1 < value2
let check2 = value1 <= value2
value2.name =
"B"
let check3 = value1 >= value2
let check4 = value1 > value2
|
Printable 定義印出的內容 description { get } 宣告
1
2
3
|
protocol Printable {
var description: String { get }
}
|
使用
1
2
3
4
5
6
7
8
9
10
11
|
struct MyName: Printable {
var name =
"路人甲"
var description: String {
return
"我的名字是 \(name)"
}
}
let value = MyName()
println(value)

|
Free Functions
Printing 印出訊息的主要函式
- print<T>(_:)
- println<T>(_:)
- println()
在 Swift 裡面,有兩個主要印出數值的函式,print() 與println() ,println() 函式可給值,也可以不用給,沒有給值時就直接印出新的一行。 它們都稱作 free functions ,因為他們不用依賴一個接收物件(receiver),可以直接呼叫使用。 print<T>(_:) 將物件文字化,在標準輸出(Standard Output)印出。 宣告
使用 要印出的物件,必須遵循 Printable 或 DebugPrintable 協定,如先前介紹,需將物件文字化。
println<T>(_:) 將物件文字化,在標準輸出(Standard Output)印出,並加上斷行。 宣告
1
|
func println<T>(object: T)
|
使用 要印出的物件,必須遵循 Printable 或 DebugPrintable 協定,如先前介紹,需將物件文字化。
1
2
|
println(
"Hello, world"
)
|
println() 直接在標準輸出,印出斷行。 宣告
使用 直接呼叫使用。
1
2
3
|
print(
"Hello, world"
)
println()
|
Algorithms
- sort<T: Comparable>(inout array: T[])
- sort<T>(inout array: T[], pred: (T, T) -> Bool) -> T[]
- sorted<T: Comparable>(array: T[]) -> T[]
- sorted<T>(array: T[], pred: (T, T) -> Bool) -> T[]
Swift 內建了許多常用的演算法,包含 排序、搜尋…等等,所以很多我們不用自己重複造車,就能享用 Swift 帶來方便的函式。 sort<T: Comparable>(inout array: T[]) 如同之前所介紹的Comparable 協定,傳入陣列的元素,必須遵循此協定才能比較並排序。 宣告
1
|
func sort<T: Comparable>(inout array: T[])
|
使用 此處宣告的 sort function 傳入的參數陣列前面多了一個inout 關鍵字,這代表的意思是,此處傳入的參數 是可以被修改並替換的。 現在將陣列傳入一個,inout 參數的函式,必須將參數明確表示,在變數前面必須加上& 。
1
2
3
|
var array = [
5
,
1
,
6
,
4
,
2
,
3
]
sort(&array)
|
常數無法被丟進inout 參數處理。
1
2
3
|
let constantArray = [
5
,
1
,
6
,
4
,
2
,
3
]
sort(&constantArray)
|
sort<T>(inout array: T[], pred: (T, T) -> Bool) -> T[] 類似之前介紹的 Array.sort,第二個參數 Closure ,在Closure 內執行的結果必須回傳 Bool 值,isOrderedBefore 表示如果回傳為 true,將排在前面,反之往後排序。 宣告
1
|
func sort<T>(inout array: [T], isOrderedBefore: (T, T) -> Bool)
|
使用
1
2
3
|
var array = [
5
,
1
,
3
,
4
,
2
,
6
]
sort(&array) { $
0
> $
1
}
|
sorted<T: Comparable>(array: T[]) -> T[] 與sort 類似,sorted 則是回傳結果陣列,不去更動原來的陣列物件。 宣告
1
|
func sorted<C : MutableCollectionType where C.Index : RandomAccessIndexType, C.Generator.Element : Comparable>(source: C) -> C
|
使用 因為不需更動array 物件,所以此處 array 前面不需加& 。
1
2
3
|
let array = [
5
,
1
,
6
,
4
,
2
,
3
]
let result = sorted(array)
|
sorted<T>(array: T[], pred: (T, T) -> Bool) -> T[] 類似之前介紹的 sort,第二個參數 Closure ,在Closure 內執行的結果必須回傳 Bool 值,isOrderedBefore 表示如果回傳為 true,將排在前面,反之往後排序。 宣告
1
|
func sorted<C : MutableCollectionType where C.Index : RandomAccessIndexType>(source: C, isOrderedBefore: (C.Generator.Element, C.Generator.Element) -> Bool) -> C
|
使用
1
2
3
|
let array = [
5
,
1
,
3
,
4
,
2
,
6
]
let result = sorted(array) { $
0
> $
1
}
|
|