- Görkem Güray/
- 100 Günde SwiftUI Notları/
- 8.Gün - Swift Fonksiyonlar - 2 : Varsayılan Değer ve Error Handling/
8.Gün - Swift Fonksiyonlar - 2 : Varsayılan Değer ve Error Handling
Table of Contents
Fonksiyon Parametreleri için Varsayılan Değer #
Fonksiyonlarımızı parametreler vasıtasıyla özelleştirebildiğimizden bahsetmiştik. Parametrelerimize varsayılan değer sağlayarak bu özelleştirmeyi daha da opsiyonel bir hale getirebiliriz.
Daha önceki dersimizde yazdığımız bir fonksiyonu inceleyelim;
func printTimesTables(for number: Int, end: Int) {
for i in 1...end {
print("\(i) x \(number) is \(i * number)")
}
}
printTimesTables(for: 5, end: 20)
Yukarıdaki kod, 1’den başlayarak herhangi bir noktaya kadar istediğimiz sayının çarpım tablosunu vermektedir. Son nokta her zaman değişken olabilir fakat çoğu zaman 10 veya 12 olmasını isteriz. Fakat bazen de bizim belirlediğimiz bir son noktaya da gitmesi gerekebilir.
Bu problemi çözebilmek için, Swift fonksiyon parametrelerine varsayılan değer atamamıza izin verir. Aşağıdaki kodda end
parametresi için 12 değeri varsayılan değer olarak atanmıştır. Biz fonksiyon çağrısı esnasında aksini belirtmezsek, 12 değeri kullanılacaktır.
func printTimesTables(for number: Int, end: Int = 12) {
for i in 1...end {
print("\(i) x \(number) is \(i * number)")
}
}
printTimesTables(for: 5, end: 20)
printTimesTables(for: 8)
printTimesTables()
fonksiyonunu iki farklı şekilde çağırabiliyoruz. İstersek iki parametreyi (for:
end:
) birden sağlarız, yada tek bir parametre (for:
) sağlar diğer parametrenin varsayılan değerini kullanırız.
Swift optimizasyon için, Array öğelerini tutmaya yetecek alandan biraz fazlasını ayırır, Array’in boyutu arttıkça ayrılan alanı da arttırır. Böylece mümkün olduğunca az bellek harcar.
var characters = ["Lana", "Pam", "Ray", "Sterling"]
print(characters.count)
characters.removeAll()
print(characters.count)
removeAll()
fonksiyonu çağrıldığında, Swift otomatik olarak Array’deki tüm öğeleri kaldıracak ve ayrılmış belleği boşaltacaktır. Fakat bazı durumlarda Array öğelerini kaldırmak fakat ayrılan belleği de tutmak isteyebiliriz. (Bir Array’deki tüm öğeleri kaldırıp, çok sayıda yeni öğe eklemek isteyebiliriz). İşte removeAll()
fonksiyonunun, öğeleri kaldırıp bellek alanını koruduğu bir işlevi de vardır.
characters.removeAll(keepingCapacity: true)
removeAll()
fonksiyonunun bu davranışı, fonksiyonların varsayılan parametre özelliği sayesinde gerçekleşir. keepingCapacity
parametresinin varsayılan değeri false
tır. Bu sayede hem öğeleri kaldırır hem de bellek alanını temizler. (Biz fonksiyon çağrısı esnasında özellikle belirtmediğimiz sürece false
olarak kalmaya devam eder.) Array’in bellek alanını korumak istediğimizde ise bu parametreyi true
olarak değiştiririz.
Fonksiyonlarda Error Handling #
Okumak istediğimiz dosyanın olmaması, indirmeye çalıştığımız verinin, internet bağlantısı kesildiği için başarısız olması gibi durumlar her zaman meydana gelebilir. Bu hataları düzgünce işlemezsek, kodumuz çökebilir. Bu sebeple, fonksiyonlarda meydana gelebilecek hatalara göre hangi davranışlarda bulunacağımızı belirlemeliyiz.
Error Handling üç adımdan oluşur;
- Swift’e, meydana gelebilecek olası hatalar için bilgi vermek.
- Hata oluştuğunda bunu haber verebilecek bir fonksiyon yazmak.
- Fonksiyonun çağrılması ve oluşabilecek hataların ele alınması.
Kullanıcının şifresini kontrol eden bir fonksiyon yazalım, şifre çok kısaysa veya çok kolaysa bir hata oluşturalım.
Swift’e, meydana gelebilecek olası hatalar için bilgi vermek. #
İşe, meydana gelebilecek olası hataları tanımlayarak başlayalım. Bu da Error
tipini temel alan bir enum oluşturmamızı gerektirmektedir.
enum PasswordError: Error {
case short, obvious
}
Yukarıdaki enum, iki olası hata durumu olduğunu söylüyor : short
ve obvious
. Bu enum ne anlama geldiğini tanımlamıyor, sadece bu durumların var olduğunu söylüyor.
Hata oluştuğunda bunu haber verebilecek bir fonksiyon yazmak. #
İkinci adımımızda bu hataları tetikleyebilecek bir fonksiyon yazacağız. Bir hata tetiklendiğinde, fonksiyon normal bir şekilde devam etmek yerine, değer geri döndürmeden hemen sonlanacaktır.
func checkPassword(_ password: String) throws -> String {
if password.count < 5 {
throw PasswordError.short
}
if password == "12345" {
throw PasswordError.obvious
}
if password.count < 8 {
return "OK"
} else if password.count < 10 {
return "Good"
} else {
return "Excellent"
}
}
Yukarıdaki kodu biraz inceleyelim;
- Bir fonksiyon, hataları kendisi işlemeden fırlatabiliyorsa, fonksiyonun geri dönüş türünden önce
throws
olarak işaretlenir. - Fonksiyon tarafından tam olarak ne tür bir hata fırlatılacağını belirtmiyoruz, sadece hata fırlatılabileceğini söylüyoruz.
- Fonksiyonun
throw
ile işaretlenmiş olması, mutlaka hata fırlatacağı anlamına gelmez, sadece olabileceğini belirtir. - Bir hata meydana geldiğinde,
throw
vePasswordError
case’lerinden birini yazıyoruz. Bu fonksiyondan hemen çıkar, yani bir String döndürmez. - Eğer bir hata fırlatılmazsa, fonksiyon normal bir şekilde davranır yani bir String döndürür.
Böylelikle hataların ele alınmasındaki ikinci adımı tamamlamış olduk.
Fonksiyonun çağrılması ve oluşabilecek hataların ele alınması. #
Bu adım üç alt adımdan oluşmaktadır.
- Hata verebilecek bir kod bloğunu
do
ile başlatmak, try
kullanarak bir veya daha fazla throw fonksiyonu çağırmak,- Fırlatılan hataları
catch
kullanarak işlemek
Örneğimizden devam edelim;
let string = "12345"
do {
let result = try checkPassword(string)
print("Password rating: \(result)")
} catch {
print("There was an error.")
}
//ÇIKTI:
//----------------------------------------
//There was an error.
checkPassword()
fonksiyonu hatasız olarak çalışırsa bir değer döndürür ve bu değer result
sabitine atanır. Ancak bir hata meydana gelirse (yukarıdaki koda göre oluşacaktır) “Password rating:”
kısmı terminale yazdırılmayacak, program akışı catch
bloğuna yönlenecektir.
try
, hata verebilecek tüm fonksiyonlar çağrılmadan önce yazılmalıdır, bu geliştiricilere bir hata oluşması durumunda normal kod akışının kesintiye uğrayacağına dair görsel bir işarettir.
do {
try throwingFunction1()
nonThrowingFunction1()
try throwingFunction2()
nonThrowingFunction2()
try throwingFunction3()
} catch {
// handle errors
}
try
’ı kullanabilmek için mutlaka bir do
bloğu içinde olmamız ve herhangi bir hatayı ele alabilecek bir veya daha fazla catch
bloğuna sahip olmamız gerekir. Çok nadir de olsa, fonksiyonun hata fırlatmayacağından kesinlikle emin olduğumuz durumda try!
şeklinde bir kullanım yapabiliriz. try!
kullanıldığında do
ve catch
bloklarının kullanımına gerek yoktur.
catch
bloğu ile belirli hataları da yakalayabiliriz. Ama mutlaka her hatanın yakalandığına emin olmalıyız.
let string = "12345"
do {
let result = try checkPassword(string)
print("Password rating: \(result)")
} catch PasswordError.short {
print("Please use a longer password.")
} catch PasswordError.obvious {
print("I have the same combination on my luggage!")
} catch {
print("There was an error.")
}
//ÇIKTI:
//----------------------------------------
//I have the same combination on my luggage!
Bu yazıyı İngilizce olarak da okuyabilirsiniz.
You can also read this article in English.