From c4a3752c53eaf7cd9ca4bd17b518b4ed8f8e83c3 Mon Sep 17 00:00:00 2001 From: AceVest Date: Sun, 19 Jun 2016 22:15:52 +0800 Subject: [PATCH] swift:functions & closures --- .../AcePlay/AcePlay.playground/Contents.swift | 8 -- .../Basics.xcplaygroundpage/Contents.swift | 104 ++++++++++++++ .../Closure.xcplaygroundpage/Contents.swift | 130 ++++++++++++++++++ .../Functions.xcplaygroundpage/Contents.swift | 56 ++++++++ .../AcePlay.playground/Sources/Basic.swift | 105 -------------- .../AcePlay.playground/Sources/Func.swift | 13 -- .../AcePlay.playground/contents.xcplayground | 8 +- .../UserInterfaceState.xcuserstate | Bin 12776 -> 13902 bytes 8 files changed, 296 insertions(+), 128 deletions(-) delete mode 100644 learn/AcePlay/AcePlay.playground/Contents.swift create mode 100644 learn/AcePlay/AcePlay.playground/Pages/Basics.xcplaygroundpage/Contents.swift create mode 100644 learn/AcePlay/AcePlay.playground/Pages/Closure.xcplaygroundpage/Contents.swift create mode 100644 learn/AcePlay/AcePlay.playground/Pages/Functions.xcplaygroundpage/Contents.swift delete mode 100644 learn/AcePlay/AcePlay.playground/Sources/Basic.swift delete mode 100644 learn/AcePlay/AcePlay.playground/Sources/Func.swift diff --git a/learn/AcePlay/AcePlay.playground/Contents.swift b/learn/AcePlay/AcePlay.playground/Contents.swift deleted file mode 100644 index 2a17f16..0000000 --- a/learn/AcePlay/AcePlay.playground/Contents.swift +++ /dev/null @@ -1,8 +0,0 @@ -//: Playground - noun: a place where people can play - -import UIKit - - -SwiftBasics() - -SwiftFunctions() diff --git a/learn/AcePlay/AcePlay.playground/Pages/Basics.xcplaygroundpage/Contents.swift b/learn/AcePlay/AcePlay.playground/Pages/Basics.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..1ff1148 --- /dev/null +++ b/learn/AcePlay/AcePlay.playground/Pages/Basics.xcplaygroundpage/Contents.swift @@ -0,0 +1,104 @@ +//: Playground - noun: a place where people can play + +import UIKit + +let str = "Hello, playground.小狗:🐶 锤子:🔨" + +// Index +let strInx:String.Index = str.startIndex +strInx.successor() +print(strInx) + +for c in str.characters { + print(c, terminator: "") +} +print() + +// Print separator & terminator +var company:Array = [ "Apple", "Google", "Facebook", "Tencent" ] +print(company[0], company[1], company[2], company[3], separator: "#", terminator: " $$$$$\n") + +printLine("Count company Array 1") +for (i,v) in company.enumerate() { // enumerate 返回的是 index value 组成的元组 + print(i, v, separator: " - ", terminator: "\n") +} + +printLine("Count company Array 2") +company.insert("Alibaba", atIndex: company.count) +for i in 0..(0.. = [] +var SetB = Set() +var SetC: Set = ["ASM", "C", "C++", "go", "Swift"] +//var SetD: Set = ["mov", "pop", "push", "xchg"] // 可以通过数组类型推断出Set的类型 +SetB.insert("A") +SetB.insert("c") +SetB.insert("c") +SetB.count +//SetC.removeFirst() +SetC.remove("ASM") + +if let removedVal = SetC.remove("ASM") { + print("\(removedVal) I'm over it.") +} else { + print("I never much cared for that.") + SetC.insert("ASM") +} + +if SetC.contains("Swift") { + print("SetC Contains Swift") +} + +for v in SetC.sort() { + print(v) +} + +printLine("Dictionary") +//var DictA = Dictionary() +//var DictB = ["KA":"VA", "KB":"VB", "KC":"VC"] +//var DictC: [String:String] = [:] +var DictD = [Int:String]() + +DictD[1] = "V1" +DictD[4] = "V2" +DictD[99] = "V3" +DictD[36] = "F4" +if let oldValue = DictD.updateValue("V4", forKey: 36) { // means: if let oldValue = DictD[36] + print("The old value for Key:36 was \(oldValue)") +} + +print("DictD Item Count: ", DictD.count) + +for (k, v) in DictD { + print("Key:", k, " Value: ", v) +} + +for key in DictD.keys.sort() { + print(key) +} + +for value in DictD.values.sort() { + print(value) +} + +let keys = [Int](DictD.keys) +print(keys) diff --git a/learn/AcePlay/AcePlay.playground/Pages/Closure.xcplaygroundpage/Contents.swift b/learn/AcePlay/AcePlay.playground/Pages/Closure.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..66a43a8 --- /dev/null +++ b/learn/AcePlay/AcePlay.playground/Pages/Closure.xcplaygroundpage/Contents.swift @@ -0,0 +1,130 @@ +//: [Previous](@previous) + +import UIKit + + +// +//闭包采取如下三种形式之一: +// 1. 全局函数是一个有名字但不会捕获任何值的闭包 +// 2. 嵌套函数是一个有名字并可以捕获其封闭函数域内值的闭包 +// 3. 闭包表达式是一个利用轻量级语法所写的可以捕获其上下文中变量或常量值的匿名闭包 +// + +// +//Swift闭包语法特点: +// 1. 利用上下文推断参数和返回值类型 +// 2. 隐式返回单表达式闭包,即单表达式闭包可以省略return关键字 +// 3. 参数名称缩写 +// 4. 尾随(Trailing)闭包语法 +// + + +/* + The sort(_:) method accepts a closure that takes two arguments of the same type as the array’s contents, and returns a Bool value to say whether the first value should appear before or after the second value once the values are sorted. The sorting closure needs to return true if the first value should appear before the second value, and false otherwise. + + */ + +let company = ["Tencent", "Apple", "Facebook", "Google", "Twitter", "Amazon"] +var sortedCompany: [String] = [] + +printLine("Sort") +sortedCompany = company.sort() +print(sortedCompany) +sortedCompany = [] + +printLine("Sort With Function A") +func backwardsA(a: String, b: String) -> Bool { + return a > b +} +sortedCompany = company.sort(backwardsA) +print(sortedCompany) +sortedCompany = [] + +printLine("Sort With Backwards Closure A [Closure Expression Syntax]") +sortedCompany = company.sort({ (a: String, b: String) -> Bool in return a>b }) +print(sortedCompany) +sortedCompany = [] + +// 参数及返回类型自动推断 +printLine("Sort With Backwards Closure B [Inferring Type From Context]") +sortedCompany = company.sort({ a, b in return a > b }) +print(sortedCompany) +sortedCompany = [] + +// 隐式返回表达式闭包,省略return +printLine("Sort With Backwards Closure C [Implicit Returns from Single-Expression Closures]") +sortedCompany = company.sort({ a, b in a > b }) +print(sortedCompany) +sortedCompany = [] + +// 简写参数名 +printLine("Sort With Backwards Closure D [Shorthand Argument Names]") +sortedCompany = company.sort({ $0 > $1 }) +print(sortedCompany) +sortedCompany = [] + +/* + There’s actually an even shorter way to write the closure expression above. Swift’s String type defines its string-specific implementation of the greater-than operator (>) as a function that has two parameters of type String, and returns a value of type Bool. This exactly matches the function type needed by the sort(_:) method. Therefore, you can simply pass in the greater-than operator, and Swift will infer that you want to use its string-specific implementation: + */ +printLine("Sort With Backwards Closure E [Operator Functions]") +sortedCompany = company.sort(>) +print(sortedCompany) +sortedCompany = [] + +// Trailing Closure +printLine("Sort With Backwards Closure F [Trailing Closure]") +sortedCompany = company.sort() { a, b in a > b} // 如果闭包参数是这个函数的最后一个参数,是可以采用尾随闭包写法 +//sortedCompany = company.sort { a, b in a > b} // 如果闭包参数是这个函数的唯一一个参数,是可以不用写括号的 +print(sortedCompany) +sortedCompany = [] + + +let digitNames = [ + 0: "零", + 1: "壹", + 2: "贰", + 3: "叁", + 4: "肆", + 5: "伍", + 6: "陆", + 7: "柒", + 8: "捌", + 9: "玖", +] +let numbers = [9876543210, 1413, 110, 64] +// map函数可能不用指定参数类型,但要指定返回值类型 +let digitString = numbers.map() { + (digit) -> String in + var n = digit // 参数digit不能在函数体内被修改 + var s = "" + while n > 0 { + s = digitNames[n % 10]! + s + n /= 10 + } + return s +} + +print(digitString) + + +printLine("Captuare Value") + +// 捕获值 +func makeIncrementer(step:Int) -> () -> Int { + var total = 0 + func inc() -> Int { + total += step + return total + } + + return inc +} + +var closureFuncA = makeIncrementer(1) +print("ClosureFuncA:", closureFuncA()) +print("ClosureFuncA:", closureFuncA()) +var closureFuncB = closureFuncA +print("ClosureFunnB:", closureFuncB()) +var closureFuncC = makeIncrementer(1) +print("ClosureFuncC:", closureFuncC()) + diff --git a/learn/AcePlay/AcePlay.playground/Pages/Functions.xcplaygroundpage/Contents.swift b/learn/AcePlay/AcePlay.playground/Pages/Functions.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..ebcfc6e --- /dev/null +++ b/learn/AcePlay/AcePlay.playground/Pages/Functions.xcplaygroundpage/Contents.swift @@ -0,0 +1,56 @@ +//: [Previous](@previous) + +import Foundation + + +func Hello() -> Void { // func Hello() -> () { } + print("Hello Swift World") +} + + +printLine("Functions") + +Hello() + +printLine("Multiple Return Types") + +func minMax(data:Array) -> (min:Int, max:Int)? { + guard data.count > 0 else { + return nil + } + + var min = data[0] + var max = data[0] + + for i in 1.. data[i] ? data[i] : min + max = max < data[i] ? data[i] : max + } + + return (min, max) +} + +var Data: Array = [3, 8, 4, 1, 0, -2, 9, 6, 7] + +if let ret = minMax(Data) { + print("Min:", ret.min, " Max:", ret.max) +} + +// 外部参数包能相同, 但内部参数名不能相同 +func sameExternalParameterNames( ExName a: Int, ExName b: Int) -> Int { + return max(a, b) +} +print(sameExternalParameterNames(ExName: 10, ExName: 20)) + +// 引用传参 +func swapTwoInts(inout a: Int, inout _ b: Int) -> Void { + let t: Int = a + a = b + b = t +} + +var IntA = 10 +var IntB = 20 +swapTwoInts(&IntA, &IntB) + + diff --git a/learn/AcePlay/AcePlay.playground/Sources/Basic.swift b/learn/AcePlay/AcePlay.playground/Sources/Basic.swift deleted file mode 100644 index dddda1f..0000000 --- a/learn/AcePlay/AcePlay.playground/Sources/Basic.swift +++ /dev/null @@ -1,105 +0,0 @@ -import UIKit - -public -func SwiftBasics() -> Void { - let str = "Hello, playground.小狗:🐶 锤子:🔨" - - // Index - let strInx:String.Index = str.startIndex - strInx.successor() - print(strInx) - - for c in str.characters { - print(c, terminator: "") - } - print() - - // Print separator & terminator - var company:Array = [ "Apple", "Google", "Facebook", "Tencent" ] - print(company[0], company[1], company[2], company[3], separator: "#", terminator: " $$$$$\n") - - printLine("Count company Array 1") - for (i,v) in company.enumerate() { // enumerate 返回的是 index value 组成的元组 - print(i, v, separator: " - ", terminator: "\n") - } - - printLine("Count company Array 2") - company.insert("Alibaba", atIndex: company.count) - for i in 0..(0.. = [] - var SetB = Set() - var SetC: Set = ["ASM", "C", "C++", "go", "Swift"] - //var SetD: Set = ["mov", "pop", "push", "xchg"] // 可以通过数组类型推断出Set的类型 - SetB.insert("A") - SetB.insert("c") - SetB.insert("c") - SetB.count - //SetC.removeFirst() - SetC.remove("ASM") - - if let removedVal = SetC.remove("ASM") { - print("\(removedVal) I'm over it.") - } else { - print("I never much cared for that.") - SetC.insert("ASM") - } - - if SetC.contains("Swift") { - print("SetC Contains Swift") - } - - for v in SetC.sort() { - print(v) - } - - printLine("Dictionary") - //var DictA = Dictionary() - //var DictB = ["KA":"VA", "KB":"VB", "KC":"VC"] - //var DictC: [String:String] = [:] - var DictD = [Int:String]() - - DictD[1] = "V1" - DictD[4] = "V2" - DictD[99] = "V3" - DictD[36] = "F4" - if let oldValue = DictD.updateValue("V4", forKey: 36) { // means: if let oldValue = DictD[36] - print("The old value for Key:36 was \(oldValue)") - } - - print("DictD Item Count: ", DictD.count) - - for (k, v) in DictD { - print("Key:", k, " Value: ", v) - } - - for key in DictD.keys.sort() { - print(key) - } - - for value in DictD.values.sort() { - print(value) - } - - let keys = [Int](DictD.keys) - print(keys) -} diff --git a/learn/AcePlay/AcePlay.playground/Sources/Func.swift b/learn/AcePlay/AcePlay.playground/Sources/Func.swift deleted file mode 100644 index 344f9ab..0000000 --- a/learn/AcePlay/AcePlay.playground/Sources/Func.swift +++ /dev/null @@ -1,13 +0,0 @@ -//import Foundation -import UIKit - -func Hello() -> Void { - print("Hello Swift World") -} - - -public -func SwiftFunctions() -> Void { - printLine("Functions") - Hello() -} \ No newline at end of file diff --git a/learn/AcePlay/AcePlay.playground/contents.xcplayground b/learn/AcePlay/AcePlay.playground/contents.xcplayground index 5da2641..90f7190 100644 --- a/learn/AcePlay/AcePlay.playground/contents.xcplayground +++ b/learn/AcePlay/AcePlay.playground/contents.xcplayground @@ -1,4 +1,8 @@ - - + + + + + + \ No newline at end of file diff --git a/learn/AcePlay/AcePlay.playground/playground.xcworkspace/xcuserdata/Ace.xcuserdatad/UserInterfaceState.xcuserstate b/learn/AcePlay/AcePlay.playground/playground.xcworkspace/xcuserdata/Ace.xcuserdatad/UserInterfaceState.xcuserstate index 4665619d02c5e2c18e12d993b0cd6ba036aedea6..5f08ca2a96df821454713de6a53f5ff0e5314444 100644 GIT binary patch literal 13902 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