Search

iOS - Swift 3 基礎語法介紹

2016-12-29 12:18 PM

此篇文章將介紹在 Apple iOS 平台開發使用的 Swift 3 基礎語法

在某些地方會使用 Java 的類似方法做比對

如此一來便能夠在某些程度上加速對 Apple iOS Swift 3 基礎語法上的了解(當然前提是你懂 Java 囉~)

  1. // 若不使用 ; 結尾也沒問題 swift 使用斷行符號結尾
  2.  
  3. // 特性 1
  4. // Swift 內的所有物件 除了 class 類別物件以外
  5. // 其他物件全部都是 pass by value (struct, enum)
  6. // 也就是說 在作為參數傳遞、指定值的時候 除了 class 類別物件以外
  7. // 其他物件都會複製一份自己 此時若更改複製後的屬性值 將不會變更原本物件的屬性值
  8. // array, dictionary, String, Int, Double 等等都是屬於 struct 的類別
  9.  
  10. // 特性 2
  11. // struct/enum 若被指定給 constant 變數(let a = someStruct)
  12. // 則此 struct/enum 將會變為 immutable 屬性值皆不可異動
  13. // 而在作為參數傳遞時的所有變數都將會是常數( func perform( name:String, value:Int) name 及 value 都是常數 不可異動 )
  14. // 此時若有可能會在方法內修改 struct/enum 的屬性值時 需要在 func 前方加入 mutating 保留字
  15. // 即可異動 struct/enum 的屬性值(詳見 protocol)
  16.  
  17. // 特性 3
  18. // Swift 會猜測變數型態 因此若無特殊需求 不需要在宣告變數時加入型態
  19.  
  20. // 印出字串
  21.  
  22. print("Hello, world!");
  23.  
  24. --
  25.  
  26. // 宣告變數
  27.  
  28. var name:Type = value;
  29. var name1, name2, name3: Type
  30.  
  31. --
  32.  
  33. // 宣告常數
  34.  
  35. let name:Type = value;
  36.  
  37. --
  38.  
  39. // 宣告 optional
  40.  
  41. var name:Type? = nil;
  42.  
  43. // 宣告為 optional 可以將變數值設定為 nil
  44. // 並可使用於 if 條件 判定是否為 nil 值(詳見 if 邏輯判斷式)
  45. // 只有 optional 變數可以使用是否為 nil 的判斷
  46.  
  47. --
  48.  
  49. // 類型轉換
  50.  
  51. var floatNum:Float = 2.353;
  52. var intNum:Int = Int(floatNum);
  53.  
  54. // print(intNum); -> 2
  55.  
  56. var string:String = "There are \(intNum) pens.";
  57.  
  58. // print(string); -> There are 2 pens.
  59.  
  60. --
  61.  
  62. // 宣告陣列
  63.  
  64. var shoppingList = ["catfish", "water", "tulips", "blue paint"];
  65.  
  66. // 指定陣列值(若超過目前陣列長度將出現 indexOutOfBound 錯誤)
  67.  
  68. shoppingList[0] = "QQ";
  69.  
  70. // 新增陣列值
  71.  
  72. shoppingList.append("TT");
  73. shoppingList += ["AA", "BB"];
  74.  
  75. // 插入陣列值
  76.  
  77. shoppingList.insert("CC", at: 2);
  78.  
  79. // 建立空陣列
  80.  
  81. var emptyArray:[String] = [String]();
  82. var emptyArray:[String] = [];
  83.  
  84. --
  85.  
  86. // 宣告 dictionary
  87.  
  88. var occupations = [
  89. "Malcolm": "Captain",
  90. "Kaylee": "Mechanic",
  91. ]
  92.  
  93. // 指定 dictionary 值(若不存在則新增至 dictionary)
  94.  
  95. occupations["QQ"] = "QQ";
  96.  
  97. // 建立空 dictionary
  98.  
  99. var emptyDictionary:[String: Float] = [String: Float]();
  100. var emptyDictionary:[String: Float] = [:];
  101.  
  102. --
  103.  
  104. // Tuple
  105. // 新型態與語法 可快速建立可儲存多個值的多個屬性
  106. // 在 func 語法內有進階應用方式(return 值)
  107.  
  108. let x: (String, Int, Double) = ("Hello", 2, 0.85)
  109. // set tuple name
  110. let (word, number, value) = x
  111.  
  112. print(word) // Hello
  113. print(number) // 2
  114. print(value) // 0.85
  115.  
  116. // with default name
  117. let x:( word: String, number: Int, value: Double) = ("Hello", 2, 0.85)
  118.  
  119. print(x.word) // Hello
  120. print(x.number) // 2
  121. print(x.value) // 0.85
  122.  
  123. // rename tuple
  124. let (w, n, v) = x
  125.  
  126. print(w) // Hello
  127. print(n) // 2
  128. print(v) // 0.85
  129.  
  130. --
  131.  
  132. // Range
  133. // 儲存開始與結束 Index 的泛型物件
  134.  
  135. struct Range<T>{
  136. var startIndex: T
  137. var endIndex: T
  138. }
  139.  
  140. // 且具簡易表示語法 ... 以及 ..<
  141.  
  142. // 範例: 取得陣列中的 subArray
  143. let array = ["a", "b", "c", "d"]
  144. var subArray1 = array[2...3] // c, d
  145. var subArray2 = array[2..<3] // c
  146.  
  147. for i in 27...104 {} // Range 可以列舉(詳見 for 迴圈)
  148.  
  149. --
  150.  
  151. // 邏輯判斷式
  152.  
  153. var big:Int = 3;
  154. var small:Int = 1;
  155.  
  156. if( big > small ){
  157. print("Yes");
  158. }
  159. else{
  160. print("No")
  161. }
  162.  
  163. // print -> Yes
  164.  
  165. // optional 應用
  166.  
  167. var optionalString: String? = "Hello"
  168. print(optionalString == nil)
  169.  
  170. var optionalName: String? = "John Appleseed"
  171. var greeting = "Hello!"
  172.  
  173. // 若 optionalName 是 nil 則不會進入
  174. if let name = optionalName {
  175. greeting = "Hello, \(name)"
  176. }
  177. else{
  178. greeting = "Hello, nobody"
  179. }
  180.  
  181. // switch
  182. // 與 java 不同的是 不需使用 break; 中斷 case 區塊
  183. // 因為 swift 進入 case 後就不會再繼續往其他 case 執行了
  184.  
  185. let vegetable = "red pepper"
  186. switch vegetable {
  187. case "celery":
  188. print("Add some raisins and make ants on a log.")
  189. case "cucumber", "watercress":
  190. print("That would make a good tea sandwich.")
  191. // 將 vegetable 值指定給 x 並判斷 x 是否以 "pepper" 結尾
  192. // 若此處直接使用 vegetable.hasSuffix 會出錯
  193. // 用 let 將 vegetable 值指定給 x 常數後即可使用 switch 判斷
  194. case let x where x.hasSuffix("pepper"):
  195. print("Is it a spicy \(x)?")
  196. default:
  197. print("Everything tastes good in soup.")
  198. }
  199.  
  200. // print -> Is it a spicy red pepper?
  201.  
  202. --
  203.  
  204. // 若值不存在 則給予初始值的方法
  205.  
  206. let nickName: String? = nil
  207. let fullName: String = "John Appleseed"
  208. let informalGreeting = "Hi \(nickName ?? fullName)"
  209.  
  210. // print(informalGreeting); -> Hi John Appleseed
  211.  
  212. --
  213.  
  214. // 基礎 for 迴圈
  215.  
  216. var total = 0
  217.  
  218. // 等同於 for( int i = 0; i < 4; i++ )
  219. for i in 0..<4 {
  220. total += i
  221. }
  222.  
  223. print(total);
  224.  
  225. // print -> 6
  226.  
  227. // 列出成員 for 迴圈
  228.  
  229. let interestingNumbers = [
  230. "Prime": [2, 3, 5, 7, 11, 13],
  231. "Fibonacci": [1, 1, 2, 3, 5, 8],
  232. "Square": [1, 4, 9, 16, 25],
  233. ]
  234. var largest = 0
  235.  
  236. // kind 為 key 值, numbers 則是 value 值
  237. // 變數名稱自訂 dictionary 本身無排序
  238. for (kind, numbers) in interestingNumbers {
  239. // 使用 in 依序列出陣列成魚
  240. for number in numbers {
  241. if number > largest {
  242. largest = number
  243. }
  244. }
  245. }
  246. print(largest)
  247.  
  248. // print -> 25
  249.  
  250. // while 迴圈
  251. // 條件成立才會進入區塊
  252.  
  253. var n = 2
  254. while n < 100 {
  255. n = n * 2
  256. }
  257. print(n)
  258.  
  259. // print -> 128
  260.  
  261. // repeat while 迴圈
  262. // 至少執行一次 條件成立才會執行下一次
  263.  
  264. var m = 2
  265. repeat {
  266. m = m * 2
  267. } while m < 100
  268.  
  269. print(m)
  270.  
  271. // print -> 128
  272.  
  273. --
  274.  
  275. // 宣告方法
  276.  
  277. // func 保留字
  278. // greet 自訂方法名稱
  279. // person: String 變數名稱及類型
  280. // -> String 方法回傳值類型 若無回傳值則不需加入
  281. func greet(person: String, day: String) -> String {
  282. return "Hello \(person), today is \(day)."
  283. }
  284. greet(person: "Bob", day: "Tuesday")
  285.  
  286. // 不需回傳值的方法
  287. func greet() {
  288. print("Testing");
  289. }
  290. greet();
  291.  
  292. // 使用自訂變數標籤(Label)
  293. // 預設將會使用變數名稱作為標籤
  294. // 若要自訂可在參數名稱前空一格後加入 或是使用 _ 表示不需使用標籤
  295.  
  296. func greet(_ person: String, on day: String) -> String {
  297. return "Hello \(person), today is \(day)."
  298. }
  299. greet("John", on: "Wednesday")
  300.  
  301. // 回傳 不定數量的多個數值(tuple)
  302.  
  303. func calculateStatistics(scores: [Int]) -> (min: Int, max: Int, sum: Int) {
  304. var min = scores[0]
  305. var max = scores[0]
  306. var sum = 0
  307. for score in scores {
  308. if score > max {
  309. max = score
  310. } else if score < min {
  311. min = score
  312. }
  313. sum += score
  314. }
  315. return (min, max, sum)
  316. }
  317. let statistics = calculateStatistics(scores: [5, 3, 100, 3, 9])
  318. // 可使用名稱取值
  319. print(statistics.sum) // 120
  320. // 或是使用索引值取值
  321. print(statistics.2) // 120
  322.  
  323.  
  324. // 傳入不定數量的多個數值
  325.  
  326. func sumOf(numbers: Int...) -> Int {
  327. var sum = 0
  328. for number in numbers {
  329. sum += number
  330. }
  331. return sum
  332. }
  333. sumOf() // 0
  334. sumOf(numbers: 42, 597, 12) // 651
  335.  
  336. // 巢狀方法
  337. // 可以在方法內再宣告一個方法
  338.  
  339. func returnFifteen() -> Int {
  340. var y = 10
  341. func add() {
  342. y += 5
  343. }
  344. add()
  345. return y
  346. }
  347. returnFifteen() // 15
  348.  
  349. // 使用其他方法作為方法的參數值
  350.  
  351. func hasAnyMatches(list: [Int], condition: (Int) -> Bool) -> Bool {
  352. for item in list {
  353. if condition(item) {
  354. return true
  355. }
  356. }
  357. return false
  358. }
  359. func lessThanTen(number: Int) -> Bool {
  360. return number < 10
  361. }
  362. var numbers = [20, 19, 7, 12]
  363. hasAnyMatches(list: numbers, condition: lessThanTen)
  364.  
  365. // 傳入使用匿名方法參數
  366. // 匿名方法不需宣告名稱及加入 func 保留字
  367. // 僅需定義參數及回傳值即可 但後方需使用 in 保留字作為區塊宣告(相對於一般方法使用的 {})
  368.  
  369. // map 為傳入方法參數 自訂轉換功能(例如轉換大小寫、更改數值) 回傳轉換後的陣列(原始陣列值不變)
  370.  
  371. // 所有數值 * 3
  372. var numbers = [20, 19, 7, 12]
  373.  
  374. numbers.map({
  375. (number: Int) -> Int in
  376. let result = 3 * number
  377. return result
  378. })
  379.  
  380. // 更簡易的寫法(由於參數類型已知 回傳類型亦同 因此一併忽略)
  381. let mappedNumbers = numbers.map({ number in 3 * number })
  382. print(mappedNumbers)
  383.  
  384. // 所有字串改為大寫
  385. var strings = ["a", "b", "c"];
  386.  
  387. strings.map({
  388. (string:String) -> String in
  389. return s.uppercased()
  390. })
  391.  
  392. // 更簡易的寫法(由於參數類型已知 回傳類型亦同 因此一併忽略)
  393. strings.map({ $0.uppercased(); })
  394.  
  395. // 亦可用於排序方面
  396. let sortedNumbers = numbers.sorted { $0 > $1 }
  397. print(sortedNumbers)
  398.  
  399. // 或是篩選陣列中的值 並將所有回傳 true 的值重新組成一個新的陣列
  400. let array = [2, 7, 15, 36, 87, 104]
  401. print( array.filter({ $0 > 20 }) ) // [36, 87, 104]
  402.  
  403. // 也可以將 array 內的值做一個運算
  404. let array = [1,2,3,4,5]
  405. print( array.reduce(0){ $0 + $1} ) // 15
  406.  
  407. --
  408.  
  409. // 宣告 class
  410.  
  411. class Shape {
  412. var numberOfSides = 0
  413. func simpleDescription() -> String {
  414. return "A shape with \(numberOfSides) sides."
  415. }
  416. }
  417.  
  418. // 具有建構子的 class
  419. // 建構子為不需加入 func 保留字也不需宣告回傳值類型的方法 名稱必須為 init
  420. // 建立物件時必須傳入參數 var ns = NamedShape(name: "PiTT");
  421. // 若加入 deinit 則是當物件要從記憶體內移除時自動被呼叫的方法
  422. // 可以在此處 release 某些物件
  423.  
  424. class NamedShape {
  425. var numberOfSides: Int = 0
  426. var name: String
  427. // 建構子
  428. init(name: String) {
  429. self.name = name
  430. }
  431. func simpleDescription() -> String {
  432. return "A shape with \(numberOfSides) sides."
  433. }
  434. }
  435.  
  436. // 若使用 init? 則表示初始化過程可能會回傳 nil
  437. // 也就是回傳一個 Optional 物件
  438.  
  439. class NamedShape{
  440. var numberOfSides: Int = 0
  441. var name: String
  442. // 建構子
  443. init?(name: String) {
  444. if( name.isEmpty ) return nil
  445. self.name = name
  446. }
  447. func simpleDescription() -> String {
  448. return "A shape with \(numberOfSides) sides."
  449. }
  450. }
  451.  
  452. // 繼承 class
  453. // 在後方加入父類別 class
  454.  
  455. class Square: NamedShape {
  456. // 使用 override 保留字表示此為覆寫父類別方法的方法
  457. // 若未加入 override 保留字 同時方法名稱、傳入參數及回傳直接相同的話
  458. // IDE 會直接報錯
  459. override func simpleDescription() -> String {
  460. return "A square with sides of length \(sideLength)."
  461. }
  462. }
  463.  
  464. // 使用欄位的 getter/setter
  465.  
  466. class Square: NamedShape {
  467. var sideLength: Double = 3.0;
  468.  
  469. var perimeter: Double {
  470. get {
  471. return 3.0 * sideLength
  472. }
  473. set {
  474. // newValue 表示傳入的參數(等號後方的值)
  475. // set 本身已隱含此預設名稱 set(newValue)
  476. // 亦可自定義名稱 使用 set(value)
  477. sideLength = newValue / 3.0
  478. }
  479. }
  480. }
  481.  
  482. var s: Square = Square();
  483.  
  484. // print(s.perimeter) -> 9.0
  485.  
  486. // 使用 willSet
  487. // willSet 表示當欄位值在 init 之外改變值的時候都會呼叫的方法
  488. // 例如以下範例為保證兩個欄位值的邊長皆相同的方法
  489.  
  490. class TriangleAndSquare {
  491. var triangle: EquilateralTriangle {
  492. willSet {
  493. square.sideLength = newValue.sideLength
  494. }
  495. }
  496. var square: Square {
  497. willSet {
  498. triangle.sideLength = newValue.sideLength
  499. }
  500. }
  501. init(size: Double, name: String) {
  502. // 此處設定欄位值並不會觸發 willSet
  503. // 所以若修改為 square = Square(sideLength: size * 2, name: name)
  504. // 則兩個欄位的邊長將會不相等
  505. square = Square(sideLength: size, name: name)
  506. triangle = EquilateralTriangle(sideLength: size, name: name)
  507. }
  508. }
  509.  
  510. var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")
  511. print(triangleAndSquare.square.sideLength) // 10
  512. print(triangleAndSquare.triangle.sideLength) // 10
  513. triangleAndSquare.square = Square(sideLength: 50, name: "larger square")
  514. print(triangleAndSquare.square.sideLength) // 50
  515. print(triangleAndSquare.triangle.sideLength) // 50
  516.  
  517. // 使用 optional 物件
  518.  
  519. let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
  520. // optional 物件使用時必須加入 ? 若物件本身為 nil 則後方表達示將會直接忽略並直接回傳 nil
  521. let sideLength = optionalSquare?.sideLength
  522.  
  523. --
  524.  
  525. // enum
  526.  
  527. // 若使用 Int 類型則 enum 的 RawValue 會預設由 0 開始自動遞增
  528. // 其他類型則必須指定各元素的 RawValue
  529. enum Rank: Int {
  530. // 若第一個元素設定為 1 則會從 1 開始遞增
  531. case ace = 1
  532. case two, three, four, five, six, seven, eight, nine, ten
  533. case jack, queen, king
  534. // 亦可宣告方法在 enum 內
  535. func simpleDescription() -> String {
  536. switch self {
  537. // 注意此處需在前方加入 . 符號
  538. // 因為是在 switch self 的 self 為 Rank 物件 所以下方的 case 可以直接使用 .ace 取得值
  539. // 若在 switch 的目標不是 enum 物件本身(或其元素) 則必須使用 Rank.ace
  540. case .ace:
  541. return "ace"
  542. case .jack:
  543. return "jack"
  544. case .queen:
  545. return "queen"
  546. case .king:
  547. return "king"
  548. default:
  549. return String(self.rawValue)
  550. }
  551. }
  552. }
  553. let ace = Rank.ace
  554. let aceRawValue = ace.rawValue
  555. print( ace.simpleDescription() ); // 字串結果的 ace
  556.  
  557. // 亦可使用以下方式取得 enum 元素
  558.  
  559. Rank(rawValue: 3)
  560.  
  561. // 搭配前面學到的 optional 方法可避免 rawValue 不存在的情況
  562.  
  563. if let convertedRank = Rank(rawValue: 3) {
  564. let threeDescription = convertedRank.simpleDescription()
  565. }
  566.  
  567. // 進階應用
  568. // 使用 enum 搭配 struct 簡化程式碼
  569.  
  570. var result: Double = 0.0
  571.  
  572. enum Operation{
  573. // 可傳遞 associate value 以便之後取得 需注意此參數與 rawValue 是不同的意義 類似於 optional 的 associate value
  574. case Constant(Double)
  575. case UnaryOperation
  576. }
  577.  
  578. var operations: Dictionary<String, Operations> = [
  579. "pi" : .Constant(M_PI)
  580. "e" : .Constant(M_E)
  581. ]
  582.  
  583. func performOperation(symbol: String){
  584. if( let operation == operations[symbol] ){
  585. switch operation {
  586. // 使用 let value 取得 associate value
  587. case .Constant(let value):
  588. result = value;
  589. default: break;
  590. }
  591. }
  592. }
  593.  
  594. --
  595.  
  596. // Struct
  597. // 與 class 非常類似 亦可包含方法與欄位 僅可繼承 Protocal
  598. // 但在作為參數傳遞時 struct 將會複製一份自己作為傳輸 而 class 則是僅傳遞記憶體位置
  599. // 因此 struct 傳遞後會有多個物件存在於不同記憶體位置
  600. // 而 class 則只會有一個記憶體位置
  601.  
  602. struct Card {
  603. var rank: Rank
  604. var suit: Suit
  605. func simpleDescription() -> String {
  606. return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
  607. }
  608. }
  609.  
  610. --
  611.  
  612. // Protocal
  613. // 類似於 Java 的 Interface
  614.  
  615. protocol ExampleProtocol {
  616. var simpleDescription: String { get }
  617. // mutating 表示此方法可能會在方法內修改 struct/enum 的屬性值
  618. mutating func adjust()
  619. }
  620.  
  621. class SimpleClass: ExampleProtocol {
  622. var simpleDescription: String = "A very simple class."
  623. var anotherProperty: Int = 69105
  624. // 此處覆寫的方法前方不需加入 mutating 保留字 因為 class 本身原本就可以覆寫自己的屬性值
  625. func adjust() {
  626. simpleDescription += " Now 100% adjusted."
  627. }
  628. }
  629.  
  630. struct SimpleStructure: ExampleProtocol {
  631. var simpleDescription: String = "A simple structure"
  632. // Struct 則必須加上 mutating 保留字 以便覆寫屬性值
  633. mutating func adjust() {
  634. simpleDescription += " (adjusted)"
  635. }
  636. }
  637.  
  638. --
  639.  
  640. // Extension
  641. // 可以擴充原本存在的 Class 功能
  642.  
  643. extension Int: ExampleProtocol {
  644. var simpleDescription: String {
  645. return "The number \(self)"
  646. }
  647. mutating func adjust() {
  648. self += 42
  649. }
  650. }
  651.  
  652. print(7.simpleDescription) // The number 7
  653.  
  654. --
  655.  
  656. // 多型
  657. // 與 Java 相同 亦可直接將變數類型指定為 Protocal
  658. // 可使用的方法只有 Protocal 內定義的方法
  659.  
  660. let protocolValue: ExampleProtocol = a
  661. print(protocolValue.simpleDescription)
  662.  
  663. --
  664.  
  665. // 錯誤處理
  666.  
  667. // 直接繼承 Error Protocal
  668. enum PrinterError: Error {
  669. case outOfPaper
  670. case noToner
  671. case onFire
  672. }
  673.  
  674. // 在會拋出異常的方法參數後方加入 throws 保留字 表示此方法會拋出異常
  675. func send(job: Int, toPrinter printerName: String) throws -> String {
  676. if printerName == "Never Has Toner" {
  677. throw PrinterError.noToner
  678. }
  679. return "Job sent"
  680. }
  681.  
  682. // 使用 do-catch 控制會拋出異常的流程
  683. // 須注意使用時在會拋出的方法前方需加入 try 保留字
  684. do {
  685. let printerResponse = try send(job: 1040, toPrinter: "Never Has Toner")
  686. print(printerResponse)
  687. }
  688. catch {
  689. print(error)
  690. }
  691.  
  692. // 亦可使用多個 catch 處理不同的異常類型
  693.  
  694. do {
  695. let printerResponse = try send(job: 1440, toPrinter: "Gutenberg")
  696. print(printerResponse)
  697. }
  698. // 處理 PrinterError.onFire 這項錯誤
  699. catch PrinterError.onFire {
  700. print("I'll just put this over here, with the rest of the fire.")
  701. }
  702. // 處理所有 PrinterError 類型的錯誤
  703. catch let printerError as PrinterError {
  704. print("Printer error: \(printerError).")
  705. }
  706. // 處理其他所有錯誤
  707. catch {
  708. print(error)
  709. }
  710.  
  711. // 或是使用 optional 方式處理異常
  712. // 會拋出異常的方法將回傳 nil
  713.  
  714. let printerSuccess = try? send(job: 1884, toPrinter: "Mergenthaler")
  715. let printerFailure = try? send(job: 1885, toPrinter: "Never Has Toner") // nil
  716.  
  717. --
  718.  
  719. // defer
  720. // 類似於 Java 的 finally
  721. // 會在 function 的所有內容執行完成後進入
  722.  
  723. var fridgeIsOpen = false
  724. let fridgeContent = ["milk", "eggs", "leftovers"]
  725. func fridgeContains(_ food: String) -> Bool {
  726. fridgeIsOpen = true
  727. defer {
  728. fridgeIsOpen = false
  729. }
  730. let result = fridgeContent.contains(food)
  731. return result
  732. }
  733.  
  734. fridgeContains("banana")
  735. print(fridgeIsOpen) // false
  736.  
  737. --
  738.  
  739. // 泛型
  740.  
  741. func makeArray<Item>(repeating item: Item, numberOfTimes: Int) -> [Item] {
  742. var result = [Item]()
  743. // 此處使用 _ ,因為實際是不需使用到此變數 所以使用 _ 直接忽略變數宣告 類似於參數傳遞的 _ 標籤
  744. for _ in 0..<numberOfTimes {
  745. result.append(item)
  746. }
  747. return result
  748. }
  749. makeArray(repeating: "knock", numberOfTimes:4) // ["knock", "knock", "knock", "knock"]
  750.  
  751. --
  752.  
  753. // where
  754. // 可加在 function 後方表示僅有符合此條件者才可進入 function 內
  755. // 例如 在定義幾乎完全相同的 function 時( 如名稱、回傳類型相同 且參數皆為泛型時 )
  756. // 在 Java 內會出現無法識別方法的編譯錯誤
  757. // 而 Swift 則可以使用 where 制定不同泛型類型對應的不同處理方法
  758.  
  759. // Sequence 表示陣列類型的父類別
  760. // where 表示 T, U 皆需實作 == 比對的方法(Equatable) 且兩者內容元素的類型相同才可進入此方法
  761. func anyCommonElements<T: Sequence, U: Sequence>(_ lhs: T, _ rhs: U) -> Int
  762. where T.Iterator.Element: Equatable, T.Iterator.Element == U.Iterator.Element {
  763. for lhsItem in lhs {
  764. for rhsItem in rhs {
  765. if lhsItem == rhsItem {
  766. return 0
  767. }
  768. }
  769. }
  770. return 1
  771. }
  772.  
  773. // 回傳為 Int 類型的相同泛型參數方法
  774. func anyCommonElements<T: Sequence, U: Sequence>(_ lhs: T, _ rhs: U) -> Int {
  775. return 2
  776. }
  777.  
  778. // 回傳為 Bool 類型的相同泛型參數方法
  779. func anyCommonElements<T: Sequence, U: Sequence>(_ lhs: T, _ rhs: U) -> Bool {
  780. return false
  781. }
  782.  
  783. // 以下三者將各自呼叫不同的方法
  784. anyCommonElements([1, 2, 3], [3]) // 0
  785. var a:Int = anyCommonElements([1, 2, 3], ["String"]) // 2
  786. var b:Bool = anyCommonElements([1, 2, 3], ["String"]) // false
  787.  
  788. --
  789.  
  790. // 執行緒
  791.  
  792. let queue:OperationQueue = OperationQueue();
  793. queue.addOperation {
  794. // Code
  795. }
  796.  
  797. --
  798.  
  799. // lazy 保留字
  800. // 會在真正使用到此變數時才進行初始化動作(僅能使用在 var 變數 不可使用在 let 常數)
  801.  
  802. lazy var calculator = Calculator() // not initialized yet
  803.  
  804. // 若要在給訂初始值時使用到 self 物件 可以使用 lazy 保留字
  805. // 若未加入 lazy 則會出現 self 尚未被初始化錯誤
  806.  
  807. lazy var t: Type = {
  808. var r = self.someProperty * 2
  809. return r
  810. }
  811.  
  812. --
  813.  
  814. // AnyObject
  815. // 如字面意義 代表任何物件型態
  816.  
  817. var any:AnyObject;
  818.  
  819. // 是否為 SomeObjecy 類型
  820. if any is SomeObject{
  821.  
  822. }
  823.  
  824. // 將值指定給 foo 前確認型態(Casting)
  825. if let foo = any as? SomeObject{
  826.  
  827. }
  828.  
  829. // Assert
  830. // Debug 時使用 在 release 時會自動忽略
  831.  
  832. // autoclosure 使用時不需加入 {}
  833. assert( () -> Bool, "message")
  834.  
  835. assert( validate(), "Validate failed" )
  836.  
各項資料連結
Swift Tour