iOS Programlama öğrenmeye başladığımızda Swift dilinin temellerini öğrenirken Closure yapısı ile karşılaşırız. En temel konulardan biri olsa da Swift dilinde oldukça önemli bir yeri bulunuyor. Çünkü bir proje de neredeyse her yerde görmemiz mümkün. Dolayısıyla, başlangıçta bu yapının mantığını anlamak daha hızlı ilerlemenize olanak sağlayacaktır.
Öyleyse, adım adım giderek bu yapıyı birlikte öğrenelim:
Closure’lar isimleri olmayan ve bir değişkene atanabilen fonksiyonlardır:
let singing \= {
print("I'm singing a song")
}
//Calling
singing()
Closure’lara parametre verebiliriz:
let singing \= { (song: String) in
print("I'm singing \\(song)")
}
//Calling
singing("Daylight")
Dönüş değeri alabiliriz:
let singingWithReturn \= { (song: String) -> String in
return "I sang \\(song)"
}
//Calling
let message \= singingWithReturn("Daylight")
print(message)
Başka bir fonksiyonun bir parametresi olabilirler. Böylece o fonksiyonun içinde de çağrılabilirler:
func prepareForSinging(action: () -> Void) {
print("I'm getting ready to sing.")
action()
print("I sang.")
}
//Üstteki fonksiyona daha önceden closure tanımladığımız değişkeni geçirdik.
prepareForSinging(action: singing)
Burası önemli :) Eğer bir fonksiyonun son parametresi bir closure ise Swift dili “Trailing Closure Syntax” adı verilen özel bir syntax kullanmamıza izin verir. Böylelikle, “prepareForSinging” fonksiyonunu çağırırken closure’u bir parametre olarak geçirmek yerine fonksiyondan hemen sonra küme parantezleri içerisinde bir closure tanımlayabiliyoruz.
Evet, bu durumda üstte yaptığımız gibi singing adında bir closure tanımlamamıza da gerek kalmıyor.
prepareForSinging() {
print("I'm singing a song.")
}
Ayrıca geriye başka parametre kalmadığı için şu şekilde yazabiliriz:
prepareForSinging {
print("I'm singing a song.")
}
Closure’lar bir fonksiyona parametre olarak verilirken ayrıca kendi parametrelerini de kabul edebilirler ve de geri değer döndürebilirler:
func prepareForSinging(action: (String) -> String) {
print("I'm getting ready to sing.")
let message \= action("Daylight")
print(message)
print("I sang.")
}
//Calling
prepareForSinging { (song: String) -> String in
return "I'm singing \\(song)"
}
“prepareForSinging” fonksiyonunun çağrılmasında , Swift, tip çıkarım (type inference) özelliği sayesinde closure’ların parametre ve dönüş tipini bağlamdan anlayabilir. Bu yüzden bunları kaldırabiliriz. Ayrıca geri değer döndürmek zorunda olduğu tek bir satır varsa “return” key ide kaldırabiliriz:
prepareForSinging { song in
"I'm singing \\(song)"
}
Bilmekte fayda var: “Shorthand Syntax” :
“song in” şeklinde closure parametresini isimlendirmek yerine otomatik isimli parametre kullanabiliriz. İlk parametre $0 ikinci $1 şeklinde…
prepareForSinging {
"I'm singing \\($0)"
}
Ek olarak böyle bir kullanım da görebilirsiniz:
Closure’ları fonksiyonlara parametre verebildiğimiz gibi bir fonksiyondan döndürülen closure da alabiliriz. “ -> (String) -> Void ” kısmı fonksiyonun bir closure döndürdüğünü, “ (String) -> Void ” kısmı ise closure parametresinin ve dönüş değerinin tipini söylüyor.
func prepareForSinging() -> (String) -> Void {
return {
print("I'm singing \\($0)")
}
}
//Calling
let returnedClosure\= prepareForSinging()
returnedClosure("London")
Tebrikler, artık bir closure syntax’ının nasıl oluştuğunu ve nasıl kullanıldığını detaylı bir şekilde öğrendiniz. Başka bir yazımda da closure yapısının projelerde kullanım nedenlerine ve daha farklı kullanım şekillerine değineceğim. Şimdi pekiştirmeniz için projelerden closure kullanımına 2 tane örnek vereceğim:
1- Parametrelerinden biri bir closure olan metodun closure tanımlanarak çağrılması (Çağrıldığı zaman tanımladığımız closure metodun tanımlandığı yerde metodun içinde çağrılacak.)
downloadData(from: "https://example.com") { downloadedData in
print("İndirilen veriyle işlem yapılıyor: \\(downloadedData)")
}
2- İlk örnekte bahsedilen parametrelerinden biri(completion) bir closure olan bir metodun tanımlanması ve metod içerisinde verdiğimiz closure’un çağrılması.
func downloadData(from url: String, completion: (String) -> Void) {
print("Veri indiriliyor: \\(url)")
// Simülasyon olarak doğrudan çağırıyoruz
let data \= "Veri: \[\\(url)\]"
completion(data)
}
