Swift Optional

Merhaba arkadaşlar ,
mobilhanem.com sitemiz için anlattığımız/yayınladığımız Swift Dersleri serimize bu yazımızda Swift Optional ile devam edeceğiz. Bir önceki yazımızda Swift Init ve Deinit konusundan bahsetmiştik. Bu derse başlamadan önce xcode’u kurmak ve playground  üzerinde swift kodu yazabilmek için bu dersimizi okumanızı tavsiye ederim.

Optional Nedir ?

Swift dilinde bir değişkenin değerinin olmaması nil değeri alabilmesi için o değişkenin optional olarak tanımlanmış olması gerekir. Bir değişken nil değeri alabiliyor ise o değişken optional bir değişkendir yani değer almasada olur. Yani değişkenin bir değeri olabilir olmayadabilir demektir.

Optional Değişken Tanımlama

var benimAdim: String?  

var benimIkinciAdim: String? = “Eren”

Yukarıda tanımladığım iki değişkende optional değişkenlerdir. Yani bu değişkenlerimiz nil değeri alabilirler.

print(benimAdim)

print(benimIkinciAdim)

Playground ‘ımızda yukarıdaki satırları yazdığımızda konsolda sırasıyla nil ve Optional(“Eren”) çıktılarını görürüz. Bu da bize benimAdim değişkenimizin değerinin nil, benimIkinciAdim değişkeninin ise değerinin  Optional(“Eren”) olduğunu gösterir.

var soyadim: String = "Buyruk"

Yukarıda optional olmayan normal bir String değişken tanımladık. Şimdi optional değişkene nil atamasının yapılabildiğini, normal türdeki bir değişkene nil atamasının yapılamadığını görelim,

benimIkinciAdim = nil

benimSoyadim = nil 

Derleyicimiz benimIkindiAdim değişkenine hata vermezken benimSoyadim değişkenimde hata verdi.  Çünkü benimSoyadim değişkenimiz optional bir değişken değildir. Bir başka deyişle her zaman mutlaka değeri olmak zorundadır. Ve bunların ardından benimIkinciAdim değişkenimizi ekrana bastıralım ve sonucunu görelim,

print(benimIkinciAdim)

Konsolda nil değerimizi gördük. Değişkenimizin bir önceki değeri Optional(“Eren”) iken nil atamamızdan sonra nil değerini almış oldu.

 Şimdi ise değişkenlerimize değerlerimizi atayalım ve hepsini birleştirip tek bir değişkene atayalım,

benimAdim = "Taha"

benimIkinciAdim = "Eren"

benimSoyadim = "Buyruk"

Şeklinde atamalarımızı yaptık.

let benimAdSoyadim = benimAdim + benimIkinciAdim + benimSoyadim

Yeni bir değişken tanımladık ve string lerimizi birleştirerek atamamızı gerçekleştirdik. Fakat derleyicimiz yine bize kızdı. 

Optional bir değişkeni (String?) optional olmayan değişkene dönüştürmeliyiz (String).  Bu işlemi yapmak içinde Optional değişkenimizi unwrap etmeliyiz.

Unwrapping Nedir ? 

Unwrapping ile Optionals tipindeki değişkenlerimizi normal tipteki değişkenlerimize çeviriyoruz.

Optional bir değişken ile normal bir türdeki değişkeni bir arada kullanamayız.Bu yüzden optional tipindeki değişkenlerimizi unwrap etmeliyiz. Bunun için Force unwrapping, Implicit unwrapping ve Optional Binding yapabiliriz.

Force Unwrapping

İlk olarak değişkenlerimizin şu an ki değerlerini tekrar hatırlayalım ve aradaki farkı daha iyi anlayalım,

print(benimAdim)

print(benimIkinciAdim)

print(benimSoyadim)

Şeklinde konsolumuza bastırdık ve  sırasıyla,

  • Optional(“Taha”)
  • Optional(“Eren”)
  • Buyruk

Değerlerimizi gördük.  Şimdi ise unwrap işlerimizi gerçekleştirelim,

var yeniAdim = benimAdim!

var yeniIkinciAdim = benimIkinciAdim!

Hemen neler olduğunu açıklayayım, Force unwrapping işlemimizi ! sembolünü kullanarak yapmaktayız. Optional değişkenimizin yanına koyduğumuzda Optional değişkeni unwrap ederek normal tipteki değişkene çeviriyoruz. (String? -> String) Böylelikle yeni oluşturduğumuz yeniAdim ve yeniIkinciAdim değişkenlerimiz Optional tipinde değil normal tipte değişkenlerimiz olmuş oluyorlar. 

Peki Force unwrapping işlemini uyguladığımız değişkenin değeri nil ise ne olur ? Eğer öyle olursa  büyük bir sorunumuz var demektir. Optional değişkenimizi Force unwrapping uyguladığımızda değeri nil olursa eğer uygulamamız crash olacaktır. Bu da yazılımcıların istemediği bir durumdur. Force Unwrapping işlemini uygulamanızı çok tavsiye etmiyorum. Eğer değerin olacağına %100 eminseniz o zaman uygulayabilirsiniz. %100 emin olmakta ne kadar doğrudur orası meçhul.

Implicit unwrapping

Burada değişkenimizi unwrap etmemize gerek yoktur. Çünkü değişkenimizi tanımladımız sırada ! sembolünü kullanarak derleyicimize bu değişkeni kullanacağım zaman kesinlikle ama kesinlikle bir değeri olacak sana söz veriyorum diyoruz. Derleyicimizde bunun için kullanacağımız zaman bize unwrap etmelisin demiyor kızmıyor. 

Bu yöntemi seçecekseniz kullandığınız değişkeni uygulama içerisinde sürekli takip edecek ve her hangi bir değer atandığından emin olmak zorunda kalacaksınız. Çünkü değişkenimizi tanımladığımız sırada bunun garantisini derleyicimize vermiştik. Değişkenlerinizi sürekli takip etmek değer atanmış mı atanmamış mı diye takip etmek çokta güzel bir yöntem değildir. Forced unwrapping te de dediğim gibi eğer değişkeninizin nil olmayacağından yani kesinlikle bir değer atanacağından eminseniz tabiki kullanabilirsiniz.

let kullaniciSoyadi: String! = "Buyruk"

let implicitKullaniciSoyadi: String = kullaniciSoyadi

print(implicitKullaniciSoyadi)

kullaniciSoyadi değişkenimizi tanımladık Forced Unwrapping ‘in aksine değişkenimizi tanımlarken ? Sembolu yerine ! sembolünü kullandık . Tekrar belirtmek istiyorum ? Sembolunu kullandığımızda derleyicimize bu değişkenin bir değeri olabilir olmayadabilir diyoruz fakat ! sembolünü kullandığımızda derleyicimize bu değişkenin ileride bir değeri olacak bunun garantisini veriyoruz diyoruz. Ardından ise kullaniciSoyadi değişkenimizi başka bir değişken tanımlayarak değerimizi ona atıyoruz. implicitKullaniciSoyadi isimli değişkenimiz normal tipte bir değişken olmuştur. Optional değildir. 

Eğer değişkenimizi kullandığımız sırada değişkenimize her hangi bir değer atamadıysak uygulamamız runtime error verir ve crash olur. Dikkat !

 Farkın daha iyi anlaşılması için aynı değişkenler ile Forced Unwrapping işlemini uygulayalım,

let kullaniciSoyadi: String? = "Buyruk"

let forcedkullaniciSoyadi: String = kullaniciSoyadi!

print(forcedkullaniciSoyadi)

Değişkenimizi Optional olarak oluşturduk ve derleyicimize bunu değişkenin değeri olabilir olmayadabilir dedik ve değişkenimize değerimizi atadık. Ardından ! sembolünü kullanarak değişkenimizi unwrap ettik ve oluşturduğumuz değişkenimize atadık ve forcedkullaniciSoyadi değişkenimizi ekrana bastırdık. 

Optional Binding

Burda da yaptığımız iş farklı olacak ama sonucumuz ve amacımız Force Unwrapping ile aynıdır. Optional tipindeki bir değişkeni normal tipteki bir değişkene çevireceğiz. Force Unwrapping e göre en önemli artısı uygulamamızın crash olmasının önüne geçmiş oluyoruz. Yani unwrapping işlemini uyguladığımız değişkenin değeri nil olsa bile uygulamamız işleyişine devam edecektir. Çok daha güvenli bir yöntemdir.

Hemen örnek bir senaryo bulalım. Kullanıcılarımız uygulamamız içerisinde profil resmi ayarlayabiliyor olsunlar. Tabi ki her kullanıcı profil resmi yüklemek istemeyebilir. Bu senaryoda resmi  veya resmin url ‘ni  tutan değişkenimizi Force Unwrapping ile yapmış olsaydık profil resmi olmayan bir kullanıcının resmini göstermeye çalıştığımızda uygulamamız crash olacaktı.  Hemen bir optional bir değişken tanımlayalım ve değerine bir string olarak bir url verelim,

let kullaniciResmiURL: String? = "https://secure.gravatar.com/avatar/220da45006025ace2e560bbd8ea1fb25?s=200&d=mm&r=g"

Evet değişkenimizi tanımladık. Şimdi de unwrap işlemimizi yapalım,

if let kullaniciResmi = kullaniciResmiURL {

    print(kullaniciResmi)

}

Evet burada ise kullaniciResmiURL değişkeni nil olmayan bir değere sahip ise if koşulumuz sağlanacak ve print(kullaniciResmi) komutu çalışacaktır. Eğer nil değere sahip ise koşulumuz sağlanmayacak ve uygulamamız akışına devam edecektir. Bu şekilde uygulamamızın crash olma ihtimalini azaltmış olduk. Optional değişkenlerinizi unwrap ederken bu yöntemi kullanmanızı şiddetle öneririm 🙂

Evet diyelim ki değişkeninizin nil olduğu durumda kullanıcınıza bir mesaj göstermek ve ya başka bir işlem yapmak istiyorsunu o zaman yapmanız gerek iş sadece bir else eklemek ve else bloğunda yapmak istediğiniz işlemi yapmak,

if let kullaniciResmi = kullaniciResmiURL {

    print(kullaniciResmi)

} else {

    print(“Kullanıcı ‘nın resim URL ‘i yoktur. ”)

}

Şeklinde değişkenimizin nil olma durumunuda ele almış olduk. If statement ımızda tek bir koşul yerine bir çok koşul yazarakta kullanabiliriz.

If Let Yerine Guard Let 

Daha önceki derslerde If let Ve Guard let arasındaki farkları göstermiştim şimdi de yukarıda yaptığımız işlemi guard let kullanarak tekrar edelim. Guard let kullanarak yazdığımız kod un okunabilirliğini artırmakla kalmayıp yazdığımız kod satır sayısınıda azaltmış oluyoruz. Hemen kullanıcımızın resminin olup olmadığını kontrol eden bir fonksiyon yazalım,

func kullanicininResminiKontrolEt(){

    guard let kullaniciResmi = kullaniciResmiURL else {

        print("Kullanıcı ‘nın resim URL ‘i yoktur. ")
        return
    }

    print(kullaniciResmi)
}

Fonksiyonumuz ’un çalışma mantığı şu şekilde olacaktır, kullaniciResmiURL değişkenimizin değeri nil ise konsola Kullanıcı ‘nın resim URL ‘i yoktur.  Yazısını bastıracak ve ardından fonksiyonun çağırıldığı yere return edecektir yani çağırıldığı yere geri dönecektir alttaki print(kullaniciResmi) komutu hiç çalışmayacaktır. Eğer kullaniciResmiURL değişkenimizin değeri nil değil ise else bloğu çalışmayacak ve print(kullaniciResmi) komutu çalışacak ardından ekrana kullaniciResmi değişkeninin değerine bastıracak sonrada fonksiyonun çağırıldığı yere geri dönecektir.

Dikkatinizi çekmek istediğim durumlardan birisi kullaniciResmi değişkeninin scope ‘u if let kullanırken sadece if bloğunun içerisinde iken guard let kullandığımızda ise bloğunun dışınada uzanmaktadır. 

 print(“Kullanıcı ‘nın resim URL ‘i yoktur. “)  komutumuz bu durumda kullaniciResmi değişkenimiz nil olduğunda çalışacaktır ve böylece değişkenimizin nil olduğu  durum daha önce bulanacaktır. 

Böylelikle bir dersimizin daha sonuna gelmiş bulunuyoruz.  Görüşmek üzere ?

let steveJobsQuote = “You can build your own things that other people can use. And once you learn that, you’ll never be the same again..”

print(steveJobsQuote)

34

Taha Eren Buyruk

Başkent Üniversitesi Bilgisayar Mühendisliği.

Yorum Yaz

Haftalık Bülten

Mobilhanem'de yayınlanan dersleri haftalık mail almak ister misiniz?