Closures - Kapatmalar - 3


Bir closure dıştaki bloğun değişkenlerini kullanabilir. Closure’lar bu bakımdan iç içe fonksiyonlara benzetilebilir.
Örneğin:
var x = 10
func foo(){
let i = 20
let f: () -> Int = {() -> Int in return i * x } // let f = { i * x }
print(f())
}
foo() // 200
İçteki fonksiyonların ya da closure’ların dış bloktaki değişkenleri kullanmasına Swift terminolojisinde (C++’ta da aynı terim kullanılıyor) “capturing” denilmektedir. Capture işlemini derleyici arka planda etkin olarak optimize etmektedir.
Örneğin:
func foo()
{
var i = 20
let f: () -> Void = { i *= 2 }
print(i) // 20
f()
print(i) // 40
}
foo()
foo()
Capture edilen değişkenler faaliyet alanını kaybetse bile derleyici bunun kalıcılığını sağlamaktadır. Örneğin bir fonksiyon iç bir fonksiyonla ya da closure ile geri dönebilir. Bu durumda bu iç fonksiyon ya da closure dış fonksiyonun değişkenlerini kullanıyorsa bunlar derleyici tarafından kalıcı hale getirilmektedir.
Örneğin:
func foo() -> () -> Int{
var i = 20
let f = { () -> Int in i *= 2; return i }
return f
}
var result: Int
var f = foo()
result = f()
print(result) // 40
result = f()
print(result) // 80
var g = foo()
result = g()
print(result) // 40
result = g()
print(result) // 80
Burada foo fonksiyonunun çalışması bittiğinde capture edilmiş i yok edilmemektedir. Tabii her foo çağırımı yeni bir i’nin yaratılmasına yol açar.
Bir fonksiyon ya da metot bir fonksiyon türünden parametre değişkenine sahipse o parametreyi dışarda bir yere aktarmıyorsa derleyici optimizasyonu için parametre @noescape özelliği ile özniteliklendirilebilir.
Örneğin:
func foo(@noescape f: () -> ()){
f()
}
foo({print(“Ok”)})
Tabi biz parametreyi dışarıda bir yere aktarıyorsak artık @noescape ile belirleme yapamayız.
Örneğin:
var a: [() -> ()] = []
func foo(@noescape f: () -> ()){
a.append(f) // error
}
Burada append fonksiyonunun parametresi @noescape ile nitelendirilmediği için çağrı errror ile sonuçlanır. Fakat örneğin:
func bar(@noescape f: () -> ()){
f()}
func foo(@noescape f: () -> ()){
bar(f) // geçerli, bar da @noescape ile nitelendirilmiş
}
foo({print(“Ok”)})