一、有關回調
我們知道,執行函數的時候,一般都有return作為返回參數了,那有return了為什么還要回調呢?
回調是為了實現異步的返回,在某些特殊的情況下,比如你執行的函數是一個長時間運行的函數,並不能直接返回給你結果,為了不影響源程序其他步驟的執行,你得繼續執行下去,等那邊產生結果了再“主動告訴你”結果是什么。
其原理不外乎:A調用B中函數,傳遞參數和自身指針,B執行完成再通過傳遞過來的指針重新調用A中函數。
在iOS開發中,實現回調的方式有:Delegate和Block。前者用變量指針實現,后者用函數指針實現。
假如我現在有一個processData的類用來處理數據,處理完之后回調給主要的Class。
二、Swift中實現回調
1.代理模式:利用protocol+引用變量
processData.swift
//
// ProcessData.swift
import UIKit
//定義協議
protocol callBackDelegate {
func callbackDelegatefuc(backMsg:String)
}
class ProcessData: NSObject{
//定義一個符合改協議的代理對象
var delegate:callBackDelegate?
func processMethod(cmdStr:String?){
if((delegate) != nil){
delegate?.callbackDelegatefuc("backMsg---by delegate")
}
}
}
ViewController.swift
//
// ViewController.swift
import UIKit
//繼承該協議
class ViewController: UIViewController,callBackDelegate{
override func viewDidLoad() {
super.viewDidLoad()
let process=ProcessData()
//把process的delegate變量指針指向自己,那樣process就能調用自己類里的函數了
process.delegate=self
//執行函數
process.processMethod("startProcess")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
//delegate回調
func callbackDelegatefuc(backMsg:String){
print(backMsg)
}
}
2.利用閉包實現:
閉包在Objective-C中被稱為Block,在Swift中被成為Closure(在Java中稱為Lambda)
2.1利用閉包變量實現回調
processData.swift
//
// ProcessData.swift
import UIKit
class ProcessData: NSObject{
//定義block
typealias fucBlock = (backMsg :String) ->()
//創建block變量
var blockproerty:fucBlock!
func processMethod(cmdStr:String?){
if let _ = blockproerty{
blockproerty(backMsg: "backMsg---by block property")
}
}
}
ViewController.swift
//
// ViewController.swift
import UIKit
class ViewController: UIViewController{
override func viewDidLoad() {
super.viewDidLoad()
let process=ProcessData()
//block回調
process.blockproerty={ (backMsg) in
print(backMsg)
}
//執行函數
process.processMethod("processStart")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
2.2 把閉包寫入函數作參數實現快速回調,可見這是一種代碼最為簡潔的方案
processData.swift
//
// ProcessData.swift
import UIKit
class ProcessData: NSObject{
//定義block
typealias fucBlock = (backMsg :String) ->()
func processWithBlock(cmdStr:String?,blockProperty:fucBlock){
blockProperty(backMsg :"backMsg---by block inside func")
}
}
ViewController.swift
//
// ViewController.swift
import UIKit
class ViewController: UIViewController{
override func viewDidLoad() {
super.viewDidLoad()
let process=ProcessData()
//函數內回調
process.processWithBlock("bbb") { (backMsg) in
print(backMsg)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
PS:如果Block帶返回值的情況下,Block是這樣定義和調用的
//定義block
typealias fucBlock = (backMsg :String) ->(String)
//函數內回調
process.processWithBlock("bbb") { (backMsg) ->(String) in
print(backMsg)
return "get msg"
}
2.3.剛使用的typealias把block給定義給一個變量了,現在直接代替進去就可以了,並且我給函數再加個String類型返回值。。
processData.swift
func processWithBlock(cmdStr:String?,blockProperty:(backMsg :String) ->())->(String){
blockProperty(backMsg :"backMsg---by block inside func")
return ""
}
swift:https://github.com/rayshen/SwiftClosure
oc:https://github.com/rayshen/callbackDemo
