Kapanışlar
Kapanışlar
Kapanışlar, CoddyKit'te ücretsiz bir Swift Academy dersidir. Bu, 1 dersinin 1. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, Swift Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. Swift Academy kursu toplamda 1 dersten oluşur.
Giriş
Merhaba,
Kapanışlar, kendi kendine yeten kod bloklarıdır. Bir kapanış, koda parametre olarak aktarılabilir veya kodun içinde kullanılabilir.
Kapanış, bir işlev türüdür. Kodun içinde aktarım yoluyla kullanılabilir. Diğer programlama dillerindeki lambda ifadelerine benzer.
Bellek yönetimi
En önemli noktalardan biri, kapanışın tanımlandığı bağlamdaki sabit ve değişken değerlerini saklayabilmesidir.
Bu saklama, kapsamına alma olarak bilinir.
Swift, bu saklama sırasında bellek yönetimini bizim için yapar.
Kapanış türleri
Kapanış türleri vardır.
- Genel işlevler, adlandırılmış kapanışlardır. Bu işlevler herhangi bir değer tutmaz.
- İç içe işlevler, adın ve içlerinde sarmalanan işlevin değerlerini taşıyabilir.
- Kapanış ifadesi ise anonim bir kapanıştır ve kendisini çevreleyen bağlamdaki verileri basit bir sözdizimiyle saklayabilir.
Kapanış sözdizimi
Kapanışların sözdizimi mümkün olduğunca basitleştirilmeye çalışılmıştır. Bunların en önemlileri şunlardır.
- Kapanışlardaki parametrelerin türleri bağlamdan çıkarılabilir.
- Dönüş değerlerinin türleri bağlamdan çıkarılabilir.
- Kapanış tek satırda döndürülebilir.
- Bağımsız değişken adları $ 0 veya $ 1 gibi kısaltmalarla ifade edilebilir.
- Sondaki kapanış sözdizimi kullanılabilir.
Bilgi
Kapanış ifadeleri, sözdizimi ve yalınlık odaklanarak kapanışların satır içinde yazılması anlamına gelir.
Kapanış sözdizimi
Aşağıdaki örnek kodda bir kapanışın sözdizimi gösterilmiştir.
{ (parameters) -> return type in
statements
}
func backward(_ s1: String, _ s2: String) -> Bool {
return s1 > s2
}
//If we didn't use closures, our code structure would be as follows.
var reversedNames = names.sorted(by: backward)
Kapanış sözdizimi
Ancak kapanış kullanarak bu türden, gereksiz yere adlandırılmış global bir kapanış tanımlamamız gerekmez.
Parametrede basit bir kapanış ifadesi tanımlamak yeterlidir. Örneğe bakalım.
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
let reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
return s1 > s2
})
print(reversedNames)
///sorted method takes closure as parameter.in anahtar sözcüğü
in anahtar sözcüğünden, kapanışın gövdesinin başladığı anlaşılır.
in anahtar sözcüğünden önce, kapanışın aldığı parametreler ve dönüş türü tanımlanmalıdır.
Türü bağlamdan çıkarma
Türleri bağlamdan çıkarma
Yukarıdaki örnekte sorted yöntemi kapanış olarak geldiği için, parametreler ve dönüş türü çıkarılarak kapanış ifadesi anlaşılabilir.
Bu nedenle bunları ayrıca tanımlamamız gerekmez.
Bu örnekte names dizisindeki değerler String olduğundan, kapanışın aldığı parametrelerin String türünde olduğu anlaşılır.
Benzer şekilde, ilgili kapanışın sıralama yapabilmesi için Bool türüne ihtiyacı vardır; bu nedenle dönüş türü Bool olarak çıkarılır.
Örnek
Aşağıdaki kullanım bu şekilde daha da sadeleşir.
Dönüş türü çıkarılarak ok işareti de koddan kaldırılabilir.
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
let reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
return s1 > s2
})
print(reversedNames)Kısa sözdizimi
Kod okuyucularının kafasını karıştırmamak için kısa sözdizimi yerine uzun sözdiziminin kullanılması tercih edilir.
Yukarıdaki sözdizimi daha da kısaltılabilir.
return anahtar sözcüğü kaldırılarak dönüş değeri kapanış ifadesiyle kısaltılabilir.
/*
In this example, the return keyword has been extracted.
It already has single expression.
There is no need to express it as an extra with return.
*/
var names = ["Coddy", "Kit"]
let reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )
print(reversedNames)Örnek
Bu örnekte return anahtar sözcüğü çıkarılmıştır.
Zaten tek bir ifade vardır ve bunu return ile ayrıca belirtmeye gerek yoktur.
reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )Ad kısaltması
Sözdizimi daha da kısaltılabilir. Yukarıdaki örnekte kapanışın iki parametre aldığını belirttik. (s1 ve s2 dahil) Türleri bağlamdan çıkarılır.
Artık bu parametreleri kısaltmalarla ifade etme ve ayrıca tanımlama zahmetinden kurtulabiliriz.
Ayrıca parametre tanımı ve dönüş değeri aktarımı olmadığından in anahtar sözcüğü de çıkarılabilir.
let names = ["Coddy", "Kit"]
let reversedNames = names.sorted(by: { $0 > $1 } )
print(reversedNames)
// In this example $0 will shortcut the first parameter and $1 will shortcut the second parameter.Örneği kısaltma
var names = ["Coddy", "Kit"]
let reversedNames = names.sorted(by: >)
print(reversedNames)
// Greater than operator takes two parameters and the rotation type is squat.TRAILING CLOSURE
Sondaki kapanış
Bir kapanış işlevine aktarılacak parametre, işlevin son bağımsız değişkeniyse ve kapanış ifadesi uzunsa, bunu sondaki kapanış ifadesi olarak yazmak daha kullanışlı olabilir.
Sondaki kapanışı sözdizimsel bir kolaylık olarak kullanabiliriz. Kodun okunabilirliğini artırmak için kullanılır.
Çoğu iOS yönteminin son parametresi kapanıştır.
Son parametre
Örneğin, bu örnekte son parametre kapanıştır.
class Animator {
class func animate(withDuration duration: Double, animations: () -> Void) {
animations()
}
}
class MyViewController {
func start() {
// With the traditional method, we can call this fund as follows.
Animator.animate(withDuration: 1, animations: { [unowned self] in
print("red")
})
}
}
MyViewController().start()Yukarıdaki kod daha az okunaklı olduğundan aşağıdaki şekilde yazılabilir
Yukarıdaki kod daha az okunaklı olduğundan aşağıdaki şekilde yazılabilir.
import Foundation
Thread.sleep(forTimeInterval: 1)
print("Background color changed to red")Örnek
Sondaki kapanış sözdizimi kullanılırken bağımsız değişken etiketini yazmamız gerekmez.
Çünkü kapanışlar artık çağrı ifadesinin bir parçası hâline gelmiştir.
func someFunctionThatTakesAClosure(closure: () -> Void) {
// function body goes here
}
// Here's how you call this function without using a trailing closure:
someFunctionThatTakesAClosure(closure: {
// closure's body goes here
})
// Here's how you call this function with a trailing closure instead:
someFunctionThatTakesAClosure() {
// trailing closure's body goes here
}Sözdizimi
Aslında sondaki kapanış sözdizimini sözdizimsel bir kolaylık olarak düşünebiliriz. Kodu daha okunabilir hâle getirir.
/*
In the example below, animations
are expressed as closure.
*/
public class func animate(withDuration: TimeInterval, animations: () -> Void)
// In traditional usage, we need to make a call like the following.
UIView.animate(withDuration: 1, animations: { [unowned self] in
self.view.backgroundColor = UIColor.red
})
/*
In this way, both the readability of the code
increases and we avoid the use of extra brackets.
If it is as above and the last parameter of the method
is closure, Swift allows to make a call like the one below.
*/
UIView.animate(withDuration: 1) { [unowned self] in
self.view.backgroundColor = UIColor.red
}Kodu sınamak için aşağıdaki kodu kullanabiliriz
Kodu sınamak için aşağıdaki kodu kullanabiliriz.
func greetThenRunClosure(name: String, closure: () -> ()) {
print("Hello, \(name)!")
closure()
}
greetThenRunClosure(name: "Paul") {
print("The closure was run")
}Kapanışın değerleri yakalaması
Kapanışın değerleri yakalaması
Bir kapanış, kendisini çevreleyen ortamı oluşturan değişkenlerin değerlerini tutabilir. Hatta bu değişkenlerin değerlerini kendi gövdesi içinden değiştirebilir ve bu değerlere erişebilir.
Bu değişkenler, tanımlandıkları özgün kapsamda artık bulunmasa bile.
Devamı
Genellikle, iç içe işlevler ve kapanış ifadeleri bu verileri birlikte saklayabilir. Dış işlevin verilerini saklayabilirler.
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
}
let incrementByTen = makeIncrementer(forIncrement: 10)
print(incrementByTen())
// returns a value of 10
print(incrementByTen())
// returns a value of 20
print(incrementByTen())
// returns a value of 30Devamı
Bir kapanışı bir sınıf özelliği olarak atarsanız, kapanış artık bu örneğe ait referansı tutmaya başlar.
Bu nedenle kapanış ile örnek arasında güçlü bir referans döngüsü oluşur.
Bellek sızıntılarına özellikle dikkat edilmelidir.
Uyarı
Kapanışlar ve işlevler referans türleridir.
@escaping
Kapanışın eşzamansız kullanıldığı pek çok noktada bu kullanıma ihtiyaç duyabiliriz.
Swift'in ilk sürümlerinde (1 ve 2) Swift parametrelerindeki kapanışlar kapsam dışına çıkabiliyordu ve daha sonra kapsam dışına çıkamaz hâle geldiler. Kapanışı kapsam dışına çıkamaz olarak aktarmamız gerektiğinde bunu özellikle belirtmemiz gerekiyordu.
Sonraki sürümlerde, bellek kullanımı açısından avantaj sağlamak için kapanış parametreleri kapsam dışına çıkamaz olarak ayarlandı.
Artık bir kapanışı kapsam dışına çıkabilir olarak tanımlamak istiyorsak @escaping anahtar sözcüğünü kullanmalıyız.
@ESCAPING anahtar sözcüğü
@ESCAPING anahtar sözcüğü
Bir işleve atanan kapanışları, işlev döndükten sonra çağırabilmek istiyorsak @escaping anahtar sözcüğünü kullanmamız gerekir.
Bir işlev için varsayılan olarak tanımlanan kapanışlar referans türleridir, ancak referans sayısını artırmazlar. Çünkü çağrı anında bu kapanışın ömrü sona erer ve referans sayısını ayrıca artırmamız gerekmez.
Ancak bir işlev çağrıldıktan sonra parametre olarak aldığımız kapanışa ihtiyacımız olacaksa, onu @escaping anahtar sözcüğüyle belirtmemiz gerekebilir.
nonEscaping
Öncelikle nonEscaping kapanışın nasıl çalıştığına bakalım.
Bu kapanış işleve parametre olarak aktarıldığında, işlevin gövdesi içinde işlenir ve ardından derleyiciye geri döner.
İşlev döndükten, yani yürütme tamamlandıktan sonra kapanış kapsamının dışında kalır ve bellekten kaldırılır.
Kapsam dışına çıkabilen kapanışı kullanma
Kapsam dışına çıkabilen kapanışı kullanma
Bir kapanış işlevi bağımsız değişken olarak aktarıldığında, kapanış işlevi dönse ve yürütme tamamlansa bile tutulmaya devam eder.
Kapanış yürütülene kadar bellekte yer kaplar. Kapsam dışına çıkabilen kapanışların birden fazla türü vardır.
Tebrikler
Tebrikler 🎉
Dersimizin sonuna geldik.
Bir sonraki derste görüşmek üzere 😎

Sıkça Sorulan Sorular
“Kapanışlar” dersi ücretsiz mi?
Evet — “Kapanışlar” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve Swift Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. Swift Academy kursu toplamda 1 dersten oluşur.
“Kapanışlar” dersinde ne öğreneceğim?
Kapanışlar Swift Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
Swift Academy öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te Swift Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 1 dersinin 1. dersidir.
“Kapanışlar” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu Swift Academy dersinde kod yazıp çalıştırabilir miyim?
Evet. Her Swift Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.