[JavaScript] 猿でもわかるクロージャ超入門 まとめ
私が今までクロージャを理解できなかった理由
★ Basic
{ ([parameters]) -> [return type] in
[statements]
}
★ Method 引数1つ(Closure (引数1つ、戻り値なし))
let api = APIManager()
api.getImage { [unowned self] (image) in
self.imageView.image = image
}
class APIManager {
func getImage(task: (image: UIImage) -> () ) {
// ダウンロード処理
task(image: downloadImage)
}
}
★ Method 引数1つ(Closure (引数1つ、戻り値有り))
let api = APIManager()
api.getImage { [unowned self] (image) in
self.imageView.image = image
return image.size
}
func getImage(task: (image: UIImage) -> CGSize) {
// ダウンロード処理
let size = task(image: downloadImage)
}
★ Method 引数1つ(Closure (引数2つ、戻り値有り))
let api = APIManager()
api.getImage { [unowned self] (image, url) in
self.imageView.image = image
print(url)
return image.size
}
func getImage(task: (image: UIImage, url: NSURL) -> CGSize) {
// ダウンロード処理
let size = task(image: downloadImage, url: url!)
}
★ Method 引数2つ(Closure (引数2つ、戻り値有り))
let url = NSURL(string: "https://teratail.com/uploads/contributed_images/78379419b2c58363c546e3e6e094a8c9.png")!
let api = APIManager()
api.getImage(url, task: { [unowned self] (image, url) in
self.imageView.image = image
print(url)
return image.size
})
func getImage(url: NSURL, task: (image: UIImage, url: NSURL) -> CGSize) {
// ダウンロード成功時
let size = task(image: downloadImage, url: url)
}
// Trailing Closures
let url = NSURL(string: "https://teratail.com/uploads/contributed_images/78379419b2c58363c546e3e6e094a8c9.png")!
let api = APIManager()
api.getImage(url) { [unowned self] (image, url) in
self.imageView.image = image
print(url)
return image.size
}
★ Method Chain
class Sample {
func method1() -> Self {
print("method1")
return self
}
func method2() -> Self {
print("method2")
return self
}
func method3() -> Self {
print("method3")
return self
}
}
let sample = Sample()
// method chain
sample.method1().method2().method3()
/*
method1
method2
method3
*/
★ Closure Chain
class Sample {
func closure1(clo1: (str: String) -> ()) -> Self {
clo1(str: "closure1")
return self
}
func closure2(clo2: (str: String) -> ()) -> Self {
clo2(str: "closure2")
return self
}
func closure3(clo3: (str: String) -> ()) -> Self {
clo3(str: "closure3")
return self
}
}
let sample = Sample()
sample.closure1 { (str) in
print(str)
}.closure2 { (str) in
print(str)
}.closure3 { (str) in
print(str)
}
/*
closure1
closure2
closure3
*/
★ シンプルClosure
// 呼び出し
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
let api = APIManager()
api.getImage { [unowned self] (image) in
self.imageView.image = image
}
}
}
import Foundation
import UIKit
class APIManager {
func getImage(task: (image: UIImage) -> () ) {
// 画像ダウンロード
let url = NSURL(string: "https://teratail.com/uploads/contributed_images/78379419b2c58363c546e3e6e094a8c9.png")
let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: nil, delegateQueue: NSOperationQueue.mainQueue())
let req = NSURLRequest(URL: url!)
let task = session.dataTaskWithRequest(req, completionHandler: { (data, response, error) in
if let imageData = data , downloadImage = UIImage(data: imageData) {
// ダウンロード成功時
task(image: downloadImage)
} else {
// エラー処理
print("Error!")
}
})
task.resume()
}
}
★ Closure簡単まとめ
// -------------------------------
// 定義と代入文それぞれに型を書いた場合
var closureA: (Int, Int) -> Int = {(valA: Int, valB: Int) -> Int in
return valA + valB
}
// 代入文のみに型を書いた場合
var closureB = {(valA: Int, valB: Int) -> Int in
return valA + valB
}
// 定義文のみに型を書いた場合
var closureC: (Int, Int) -> Int = { valA, valB in
return valA + valB
}
print(closureA(1,3)) // 4
print(closureB(2,3)) // 5
print(closureC(3,3)) // 6
// 同じ型の別の文を再代入する
closureC = { valA, valB in
return valA * valB
}
print(closureC(3,3)) // 9
// 引数にクロージャーを取るメソッドを定義
func methodA(valA: Int, valB: Int, closure: (Int, Int) -> Int) {
print(closure(valA, valB))
}
methodA(3, valB: 3, closure: closureA) // 6
methodA(3, valB: 3, closure: closureC) // 9
// ---------------------------------------
// クロージャー部分を直接記述(型も記述)
methodA(3, valB: 3, closure: {(valA: Int, valB: Int) -> Int in
return valA - valB
})
// クロージャー部分を直接記述(型は推論)
methodA(3, valB: 3, closure: { valA, valB in
return valA - valB
})
// クロージャー部分を直接記述(単独式による暗黙的リターン)
methodA(3, valB: 3, closure: { valA, valB in
valA - valB
})
// トレーリングクロージャー(Trailing Closure)
func methodB(closure: () -> ()) {
// 処理
}
// トレーリングクロージャーを使用しない場合
methodB({
})
// トレーリングクロージャーを使用した場合
methodB {
}
import UIKit
class ViewController: UIViewController {
let v: Int? = 6
override func viewDidLoad() {
super.viewDidLoad()
// クロージャーキャプチャリスト
let clo = { [weak self, max = 5, value = v] (val: Int) -> Bool in
if let value = value {
print(value + 10)
}
if let v = self?.v {
if max == v {
return true
}
return v == 1
}
return false
}
let result = clo(5)
print(result)
//=> false
}
}