クロージャについて勉強をしたので備忘録として残す
APIなどの通信は別スレッドとして処理するため、値が返ってくる前にメインスレッドで値をretrunしていて、空のデータが返ってきてしまうというものです
func getCat() -> String {
var str = "初期値"
//非同期処理を行う
let dispatchQueue = DispatchQueue(label: "Dispatch Queue", attributes: [], target: nil)
dispatchQueue.async {
//適当にちょっと重たい処理
for i in 0 ..< 1000{
if(i == 999){
str = "にゃんこ"
}
}
}
return str
}
//関数を使ってみる
print("getCat:\(getCat())") //getCat:初期値
上記の例だとメインスレッドでretunrを返してしまって欲しい値が取得できない。
流れ
①dispatchQueue.asyncで分岐される
②メインスレッドでreturnされる
③呼び出し元のgetCatでは初期値として文字が出力される
④その間にもサブスレで処理が動いている
そういう時にcompletionを使用する
func getCat(_ after:@escaping (String) -> ()){
var str = "初期値"
//非同期処理を行う
let dispatchQueue = DispatchQueue(label: "Dispatch Queue", attributes: [], target: nil)
dispatchQueue.async {
for i in 0 ..< 1000{
if(i == 999){
str = "にゃんこ"
}
}
after(str)
}
print("先にこっちが呼ばれる\(str)") //str = "初期値" のまま
}
//関数を使ってみる
getCat({ str in
print("getCat:\(str)") //getCat:にゃんこ
})
返り値はcompletionとしていてクロージャーないで完結しているのでさメインスレッドで先に値を返してしまう
可能性がありません。
completionで処理が完了するのを待機してます。
終わったらcompletionとして値を返して
呼び出しもので使用したい値が取得できている
流れ
①dispatchQueue.asyncでスレッドが分岐する
②メインスレッドでprintが呼ばれる
③クロージャー内でafterが処理の完了を待機している
④処理が終わったらafterを返り値として呼び出し元に帰ってきて欲しい値がつかえるようになる
API実行時のURLSessionは非同期で実行されるのでその中での返り値が必要な時などに有効
URLSessionまで処理はメインスレッドとして返り値が戻ってくるが
それ以後の処理ではサブスレで帰ってくるので
戻り値でインジケータ非表示にする処理があるのであればメインスレッドで囲ってあげる必要がある