Skip to main content

Swift Closure Nedir? Nasıl Çalışır?

00:02:30:13

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:

swift
let singing \= {  
    print("I'm singing a song")  
}  
//Calling  
singing()

Closure’lara parametre verebiliriz:

swift
let singing \= { (song: String) in  
    print("I'm singing \\(song)")  
}  
//Calling  
singing("Daylight")

Dönüş değeri alabiliriz:

swift
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:

swift
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.

swift
prepareForSinging() {  
    print("I'm singing a song.")  
}

Ayrıca geriye başka parametre kalmadığı için şu şekilde yazabiliriz:

swift
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:

swift
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:

swift
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…

swift
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.

swift
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.)

swift
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ı.

swift
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)  
}