歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Swift函數和閉包

Swift函數和閉包

日期:2017/3/1 9:17:12   编辑:Linux編程

簡介:本文主要講:函數的定義,外部參數的用處,無返回類型的三種函數定義方式

閉包的定義,閉包的概念和用法,尾隨閉包的寫法,解除循環引用的方法

一、函數:

代碼實現

  • 函數的定義
    • 格式 func 函數名(行參列表) -> 返回值 {代碼實現}
    • 調用 let result = 函數名(值1, 參數2: 值2...)
func sum(a: Int, b: Int) -> Int {
    return a + b
}

let result = sum(10, b: 20)
  • 沒有返回值的函數,一共有三種寫法
    • 省略
    • ()
    • Void
func demo(str: String) -> Void {
    print(str)
}
func demo1(str: String) -> () {
    print(str)
}
func demo2(str: String) {
    print(str)
}

demo("hello")
demo1("hello world")
demo2("olleh")
  • 外部參數
    • 在形參名前再增加一個外部參數名,能夠方便調用人員更好地理解函數的語義
    • 格式:func 函數名(外部參數名 形式參數名: 形式參數類型) -> 返回值類型 { // 代碼實現 }
    • Swift 2.0 中,默認第一個參數名省略
func sum1(num1 a: Int, num2 b: Int) -> Int {
    return a + b
}

sum1(num1: 10, num2: 20)

二、閉包:

與 OC 中的 Block 類似,閉包主要用於異步操作執行完成後的代碼回調,網絡訪問結果以參數的形式傳遞給調用方

閉包的定義

  • 定義一個函數
//: 定義一個 sum 函數
func sum(num1 num1: Int, num2: Int) -> Int {
    return num1 + num2
}
sum(num1: 10, num2: 30)

//: 在 Swift 中函數本身就可以當作參數被定義和傳遞
let mySum = sum
let result = mySum(num1: 20, num2: 30)
  • 定義一個閉包
    • 閉包 = { (行參) -> 返回值 in // 代碼實現 }
    • in 用於區分函數定義和代碼實現
//: 閉包 = { (行參) -> 返回值 in // 代碼實現 }
let sumFunc = { (num1 x: Int, num2 y: Int) -> Int in
    return x + y
}
sumFunc(num1: 10, num2: 20)
  • 最簡單的閉包,如果沒有參數/返回值,則 參數/返回值/in 統統都可以省略
    • { 代碼實現 }
let demoFunc = {
    print("hello")
}
 

基本使用

GCD 異步

  • 模擬在後台線程加載數據
func loadData() {
    dispatch_async(dispatch_get_global_queue(0, 0), { () -> Void in
        print("耗時操作 \(NSThread .currentThread())")
    })
}
  • 尾隨閉包,如果閉包是最後一個參數,可以用以下寫法
  • 注意上下兩段代碼,} 的位置
func loadData() {
    dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in
        print("耗時操作 \(NSThread .currentThread())")
    }
}
  • 閉包的簡寫,如果閉包中沒有參數和返回值,可以省略
func loadData() {
    dispatch_async(dispatch_get_global_queue(0, 0)) {
        print("耗時操作 \(NSThread .currentThread())")
    }
}

自定義閉包參數,實現主線程回調

  • 添加沒有參數,沒有返回值的閉包
override func viewDidLoad() {
    super.viewDidLoad()

    loadData {
        print("完成回調")
    }
}

// MARK: - 自定義閉包參數
func loadData(finished: ()->()) {

    dispatch_async(dispatch_get_global_queue(0, 0)) {
        print("耗時操作 \(NSThread.currentThread())")

        dispatch_sync(dispatch_get_main_queue()) {
            print("主線程回調 \(NSThread.currentThread())")

            // 執行回調
            finished()
        }
    }
}
  • 添加回調參數
override func viewDidLoad() {
    super.viewDidLoad()

    loadData4 { (html) -> () in
        print(html)
    }
}

/// 加載數據
/// 完成回調 - 傳入回調閉包,接收異步執行的結果
func loadData4(finished: (html: String) -> ()) {

    dispatch_async(dispatch_get_global_queue(0, 0)) {
        print("加載數據 \(NSThread.currentThread())")

        dispatch_sync(dispatch_get_main_queue()) {
            print("完成回調 \(NSThread.currentThread())")

            finished(html: "<h1>hello world</h1>")
        }
    }
}

循環引用

  • 建立 NetworkTools 對象
class NetworkTools: NSObject {

    /// 加載數據
    ///
    /// - parameter finished: 完成回調
    func loadData(finished: () -> ()) {
        print("開始加載數據...")

        // ...
        finished()
    }

    deinit {
        print("網絡工具 88")
    }
}
  • 實例化 NetworkTools 並且加載數據
class ViewController: UIViewController {

    var tools: NetworkTools?

    override func viewDidLoad() {
        super.viewDidLoad()

        tools = NetworkTools()
        tools?.loadData() {
            print("come here \(self.view)")
        }
    }

    /// 與 OC 中的 dealloc 類似,注意此函數沒有()
    deinit {
        print("控制器 88")
    }
}

運行不會形成循環引用,因為 loadData 執行完畢後,就會釋放對 self 的引用

  • 修改 NetworkTools,定義回調閉包屬性
/// 完成回調屬性
var finishedCallBack: (()->())?

/// 加載數據
///
/// - parameter finished: 完成回調
func loadData(finished: () -> ()) {

    self.finishedCallBack = finished

    print("開始加載數據...")

    // ...
    working()
}

func working() {
    finishedCallBack?()
}

deinit {
    print("網絡工具 88")
}

運行測試,會出現循環引用

解除循環引用

  • 與 OC 類似的方法
/// 類似於 OC 的解除引用
func demo() {
    weak var weakSelf = self
    tools?.loadData() {
        print("\(weakSelf?.view)")
    }
}
  • Swift 推薦的方法
loadData { [weak self] in
    print("\(self?.view)")
}
  • 還可以
loadData { [unowned self] in
    print("\(self.view)")
}

閉包(Block) 的循環引用小結

  • Swift

    • [weak self]
      • self是可選項,如果self已經被釋放,則為nil
    • [unowned self]
      • self不是可選項,如果self已經被釋放,則出現野指針訪問
  • Objc

    • __weak typeof(self) weakSelf;
      • 如果self已經被釋放,則為nil
    • __unsafe_unretained typeof(self) weakSelf;
      • 如果self已經被釋放,則出現野指針訪問

Ubuntu 15.10安裝部署Swift開發環境 http://www.linuxidc.com/Linux/2016-01/126995.htm

Swift 的變化:從 2.2 到 3.0 會帶來什麼 http://www.linuxidc.com/Linux/2015-12/126440.htm

Swift 正式開源,同時開源 Swfit 核心庫和包管理器 http://www.linuxidc.com/Linux/2015-12/125847.htm

Apple Swift學習教程 http://www.linuxidc.com/Linux/2014-09/106420.htm

使用 Swift 構建一個 iOS 的郵件應用 http://www.linuxidc.com/Linux/2014-08/105542.htm

Swift 2.0開源化 http://www.linuxidc.com/Linux/2015-06/118594.htm

Linux下搭建Swift語言開發學習環境 http://www.linuxidc.com/Linux/2015-12/125983.htm

Swift 的詳細介紹:請點這裡

Copyright © Linux教程網 All Rights Reserved