最近在學習swift,期間也看了不少教程和大神的博客,最後把筆記放這裏,方便查看複習~swift
附上學習資料地址:w3cschool-Swift 教程 、 YungFan大神的簡書(推薦看一下,有些知識點總結地簡直通俗易懂)api
函數就是oc中的方法數組
常規格式:markdown
func 函數名(參數列表) -> 返回值類型 {
代碼塊
return 返回值
}
複製代碼
一、無參+無返回值閉包
//常規寫法
func about() -> Void {
print("iPhone Xs Max")
}
// 調用函數
about()
// 簡單寫法
// 若是沒有返回值,Void能夠寫成()
func about1() -> () {
print("iPhone Xs Max")
}
about1()
// 若是沒有返回值,後面的內容能夠都不寫
func about2() {
print("iPhone Xs Max")
}
about2()
複製代碼
二、無參+有返回值app
func readMessage() -> String {
return "吃飯了嗎?"
}
var str = readMessage()
print(str)
複製代碼
三、有參+無返回值異步
func call(phoneNum : String) {
print("打電話給\(phoneNum)")
}
call("18888888888")
複製代碼
四、有參+有返回值函數
func sum(num1 : Int, num2 : Int) -> Int {
return num1 + num2
}
var result = sum(num1: 20, num2: 30)
print(result)
複製代碼
五、返回值爲複雜類型oop
//大體意思爲,返回值是一個元組類型
func getInfo(info:String) -> (name:String, age:Int) {
let infos = info.components(separatedBy: ",")
//注意,第二個類型要轉換一下,而且加!
return (infos[0], Int(infos[1])!)
}
let person:(name:String, age:Int) = getInfo(info: "zhangsan,20")
print(person.name)
print(person.age)
複製代碼
一、函數的參數是常量;學習
二、形參標籤+形參名稱,也就是:外部參數名+內部參數名+類型;
函數參數的常規寫法
func addFunc(num1 a: Int,num2 b: Int) -> Int {
return a + b
}
let result = addFunc(num1: 5, num2: 5)
print(result) //10
複製代碼
簡寫,省略
func addFunc(_ a: Int,_ b: Int) -> Int {
return a + b
}
let result = addFunc(5, 5)
print(result) //10
複製代碼
三、能夠設置默認參數(在沒有傳入參數的狀況下);
func makecoffee(type :String = "冰美式") -> String {
return "來一杯\(type)。"
}
let coffee1 = makecoffee(type: "拿鐵")
print(coffee1) //來一杯拿鐵。
let coffee2 = makecoffee()
print(coffee2) //來一杯冰美式。
複製代碼
四、可變參數:swift中接受參數的個數不肯定,但類型要相同;
func total(numbers:Int...) -> Int {
var sum = 0
for i in numbers {
sum += i
}
return sum
}
let res1 = total()
let res2 = total(numbers:10)
let res3 = total(numbers:10,20)
let res4 = total(numbers:10,20,30)
print(res1) //0
print(res2) //10
print(res3) //30
print(res4) //60
複製代碼
五、inout引用類型:通常參數只是傳遞一個值進來,若是想改變外部參數就要用到inout,相似block中的__block;
func changeInt(a: inout Int, b: inout Int) {
a += 12
b += 100
}
var a = 10
var b = 20
print("調用前:a=\(a), b=\(b)")
//打印:調用前:a=10, b=20
changeInt(a: &a, b: &b)
print("調用後:a=\(a), b=\(b)")
//打印:調用後:a=22, b=120
複製代碼
六、函數的嵌套:內嵌的函數只能在該函數裏面調用
一、函數的引用類型 二、每一個函數都有本身的類型 三、定義+使用->代碼示例 四、嵌套函數(一個函數做爲另外一個函數的參數 、一個函數做爲另外一個函數的返回值)
函數類型的使用:
//定義一個函數
func addTwoInts(a : Int, b : Int) -> Int {
return a + b
}
//這個函數的類型是:(Int, Int) -> Int
//因而,咱們能夠這麼使用:
var mathFunction : (Int, Int) -> Int = addTwoInts
//而後能夠這麼調用
let res = mathFunction(10, 20)
print(res)
複製代碼
一個函數做爲另外一個函數的參數:
//定義一個函數
func addTwoInts(a : Int, b : Int) -> Int {
return a + b
}
//這個函數的類型是:(Int, Int) -> Int
//做爲一個參數傳入另外一個函數
//參數名: 函數類型
// 將函數的類型做爲函數的參數
func printResult(a : Int, b : Int, calculateMethod : (Int, Int) -> Int) {
print(calculateMethod(a, b))
}
//調用自定義函數
printResult(a: 10, b: 20, calculateMethod: addTwoInts)
//也能夠調用 手寫一個閉包穿進去
printResult(a: 12, b: 22, calculateMethod: {(m: Int, n: Int) -> Int in return m + n})
複製代碼
一個函數做爲另外一個函數的返回值:
//定義兩個函數
func addTwoInts(a : Int, b : Int) -> Int {
return a + b
}
func multiplyTwoInt(a : Int, b : Int) -> Int {
return a * b
}
//函數做爲返回值
func getResult(a:Int) -> (Int, Int)->Int{
if a > 10 {
return addTwoInts
}
else{
return multiplyTwoInt
}
}
//調用返回的函數
let res1 = getResult(a: 2)(10,20)
print(res1) //200
let res2 = getResult(a: 12)(10,20)
print(res2) //30
複製代碼
閉包:是一個能夠被傳遞、引用的獨立模塊;
它可以捕捉、存儲 定義在它上下文中的任何常量和變量,也就是說:閉合幷包裹 其裏面的常量和變量
,所以叫作:閉包
閉包和函數同樣,都是引用類型
分爲三種形式:
計算一個數的特定值,好比平方
函數的寫法
func square(num: Int) -> Int{
return num * num
}
//調用
square(num: 5)
複製代碼
閉包的寫法
let squareCloure = { (num: Int) -> Int in
return num * num
}
//調用
squareCloure(6)
複製代碼
條件
//這是一個函數,它裏面有一個參數 須要傳入一個函數/閉包
//從數組中篩選指出合適的數據組成新的數組
func getList(score:[Int], con:(Int)->Bool) -> [Int]{
var newScore:[Int] = [Int]()
for item in score {
//把每個元素傳入con方法,根據返回值判斷是否執行{}
if con(item) {
newScore.append(item)
}
}
return newScore
}
//已知數組
let scoreArray = [75,60,95,45,85]
複製代碼
函數方式處理
//函數的方式傳參,先聲明一個函數
func method(num: Int) -> Bool{
return num > 50
}
let newArrayM = getList(score: scoreArray, con: method)
print(newArrayM) //[75, 60, 95, 85]
複製代碼
閉包方式處理
//閉包方式傳參,寫法1
let closure = {(num: Int) -> Bool in
return num > 50
}
let newArrayC = getList(score: scoreArray, con: closure)
print(newArrayC) //[75, 60, 95, 85]
//閉包方式傳參,寫法2
let newArrayC2 = getList(score: scoreArray, con:{(num: Int) -> Bool in return num > 50})
print(newArrayC2) //[75, 60, 95, 85]
複製代碼
一、由in
關鍵字,將閉包分紅兩個部分:參數與返回值、閉包體 二、與函數不一樣的一點:參數不能設置默認值,其餘與函數同樣 三、參數名稱有縮寫功能,經過$0、$一、$2
依次進行參數的調用 四、能夠根據不一樣狀況進行簡寫:
->
和 返回值類型
(根據後面表達式能夠推斷返回值是一個Bool)let newArrayC2 = getList(score: scoreArray, con:{(num: Int) in return num > 50})
複製代碼
參數類型
和 括號
(根據函數的參數可推斷傳進來的必然是Int)let newArrayC2 = getList(score: scoreArray, con:{num in return num > 50})
複製代碼
return
(由於是單行語句,能夠省略return)let newArrayC2 = getList(score: scoreArray, con:{num in num > 50})
複製代碼
參數聲明
和 in
let newArrayC2 = getList(score: scoreArray, con:{$0 > 50})
複製代碼
閉包能夠從上下文環境中捕獲常量、變量,並在本身的做用域內使用
Swift最簡單的閉包形式是嵌套函數,也就是定義在其餘函數的函數體內的函數,嵌套函數能夠捕獲其外部函數全部的參數以及定義的常量和變量
//這裏是一個嵌套函數,也能夠當作 返回值是一個閉包
func makeIncrementor(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementor() -> Int {
//在閉包裏能夠捕獲到本方法外的變量
runningTotal += amount
return runningTotal
}
return incrementor
}
let incrementByTen = makeIncrementor(forIncrement: 10)
print(incrementByTen())// 返回的值爲10
複製代碼
按我的理解就是爲了增長可讀性,閉包的寫法改了個格式
條件:有一個函數,閉包是這個函數的最後一個參數 作法:省略閉包的形參,並把小括號提早,最後使用{}
進行閉包的傳遞 好處:增長可讀性
示例:
//函數,同時 閉包是最後一個參數
func doSomething(info:String, clousre:(String)->Void){
clousre(info)
}
//正常調用
doSomething(info: "Hello", clousre: { str in print(str) })
//使用尾隨閉包進行函數調用
doSomething(info: "World") { str in
print(str)
}
複製代碼
使用@escaping
放在閉包形參類型以前,代表這是一個逃逸閉包,這個閉包會在 函數結束以後
被調用。
用途:逃逸閉包經常使用於異步回調
//聲明一個變量用於測試
var x = 10
//聲明一個存放閉包的數組
var closureArray :[()->Void] = [()->Void]()
//爲了對比,先定義一個函數,參數是一個正常閉包
func normolClosure(closure:()->Void){
closure()
}
//再定義一個函數,參數是一個逃逸閉包
//把閉包 存儲到 閉包數組中,但沒有調用。等最後調用數組中的閉包
func escapeClosure(closure: @escaping ()->Void){
print("函數開始")
closureArray.append(closure)
print("函數結束")
}
print("調用函數前,檢測 x = \(x)")
/*
調用正常閉包函數
因爲閉包是最後一個參數,能夠增長可讀性,使用尾隨閉包
*/
normolClosure {
x = 100
}
//打印100 由於閉包在函數裏面執行了
print("調用正常閉包函數後,檢測 x = \(x)")
//調用逃逸閉包函數
escapeClosure {
x = 200
}
//此時仍是100,由於沒有調用 逃逸閉包
print("調用逃逸閉包函數後,檢測 x = \(x)")
//在函數外面調用逃逸閉包
closureArray.first?()
print("函數外面調用逃逸閉包,檢測 x = \(x)")
/*
打印:
調用函數前,檢測 x = 10
調用正常閉包函數後,檢測 x = 100
函數開始
函數結束
調用逃逸閉包函數後,檢測 x = 100
函數外面調用逃逸閉包,檢測 x = 200
*/
複製代碼
使用@autoclosure
放在閉包形參類型以前,代表這是一個自動閉包。
用於包裝函數參數的表達式,不接受任何參數
,被調用時會返回被包裝在其中的表達式的值
//自動閉包
func printIfTrue(predicate:@autoclosure ()->Bool){
if predicate() {
print("is true")
}
else{
print("is false")
}
}
//直接進行調用了,Swift 將會把 2 > 1 這個表達式自動轉換爲 () -> Bool。這樣咱們就獲得了一個寫法簡單、表意清楚的表達式。
printIfTrue(predicate: 2>1)
printIfTrue(predicate: 2<1)
複製代碼
方案一:weak
經過weak修飾self對當前類進行弱引用
self屬於可能有值也可能沒有值的狀況,所以weakSelf是一個可選類型
又由於當前self必定存在,不然根本都不在這個方法裏,因此在調用的時候可使用強制解包(!),
weak var weakSelf = self
someView.block = {
//執行當前類的某個方法
weakSelf!.refreshView()
}
複製代碼
方案二:也是weak,屬於方案一的簡寫
someView.block = { [weak self] in
//執行當前類的某個方法
self?.refreshView()
}
複製代碼
方案三:unowned
unowned有點相似oc中的unsafe_unretained
它表示:即便它本來引用的對象被釋放了,扔會保持着對這個已經被釋放的對象有一個無效的引用
,所以它不能是可選值,也不會指爲nil
someView.block = { [unowned self] in
//執行當前類的某個方法
self.refreshView()
}
複製代碼