Swift: Completion Handler

Completion handler, Swift kodu yazarken size birçok durumda yardımcı olacaktır. Gelin birlikte ne olduğunu ve nasıl kodlandığını öğrenelim!

Nadin Tamer
TurkishKit
5 min readFeb 7, 2020

--

Merhaba sevgili TurkishKit okuyucuları! 👋🏻 Bugünkü yazımızda Swift dilinde kod yazarken karşımıza sık sık çıkan completion handler konseptinin ne olduğunu, hangi amaçla kullanıldığını ve nasıl yazıldığını öğreneceğiz. Swift dağarcığınıza, işinize bolca yarayacak olan yeni bir kavram eklemeye hazır mısınız? O zaman hadi başlayalım! 🤩

Completion Handler Nedir?

Swift’te completion handler (“tamamlanma işleyicisi”), bir fonksiyonun işlemleri bittiğinde çağırılan kod bloğuna verilen isimdir. Completion handler, aslında closure adı verilen bir kod tipinden oluşmaktadır. Closure, uygulamanızın farklı yerlerine geçirilip kullanılabilen bağımsız bir kod bloğuna verilen isimdir. Bugünkü konumuz completion handler olduğundan closure kavramının detaylarına girmeyecek olsak da, Apple’ın dokümantasyonundan bu konuda daha fazla bilgi alabilirsiniz (veya sonraki bir yazımızı da bekleyebilirsiniz!). 😉

Aşağıdaki görsel üzerinden completion handler bloklarının çalışma şeklini daha iyi bir şekilde anlayabiliriz:

Completion handler bloklarının çalışma şekli.

İlk olarak, completion handler bloğunu eklediğimiz ana fonksiyon çağrılır ve fonksiyonun gövde kısmında yer alan satırlar çalışır (yani fonksiyonun ana kısmı). Bu kısım tamamlandığında ise completion handler çağrılır ve bu bloğun içerisinde yer alan kodlar çalışır. Burada önemli olan nokta, ana fonksiyonun ve completion handler bloğunun her zaman arka arkaya çalışmadığıdır: Ana fonksiyon çalışırken, arka planda aynı zamanda başka kod blokları da çalışabilir.

Completion Handler Ne Zaman Kullanılır?

Peki, completion handler denilen bu kod bloklarını ne zaman kullanmak isteyebiliriz? Aklınıza ilk olarak gelen soru belki de, “Direkt olarak arka arkaya iki normal fonksiyon çağıramaz mıyız?” oldu, ve bazı durumlarda gerçekten de bunu yapabiliriz. Ancak bazen, çalışması uzun sürecek olan bir fonksiyonumuz olabilir.

Diyelim ki bir internet sitesinden uygulamamıza veri çekmek istiyoruz. Elbette ki bu kodun çalışması, biraz zaman alacaktır. Peki bu işlem yürürken uygulamamızın geri kalanının tamamen durup, ekranın donmasını mı istiyoruz? Tabii ki hayır! ❌

Böyle bir durumu önlemek için, asenkron bir şekilde fonksiyonları çağırabiliriz. Bu konsepti anlamak için ilk olarak thread kavramını anlamalıyız. Thread (kelime anlamı olarak iplik) kavramını, bir nevi çalışacak görevlerin sıralı bir listesi olarak düşünebiliriz. Aynı “thread” üzerinde yer alan işlemler, teker teker ve sıralı bir şekilde çalışmak zorundadır, ancak birden fazla “thread” kullanarak aynı anda birden fazla görevin çalışmasını sağlayabiliriz.

Şimdi asenkron çalışan fonksiyonlara geri dönelim. Senkron çağırmaların ana özelliği, sırayla çalışmalarıdır: Bir fonksiyonun işi bitene kadar, öbürünün işi başlamaz. Senkron çağırmaların aksine, asenkron çağırmalar sırayla çalışmak zorunda değildir. Bir fonksiyon çağrılıp işine devam ederken, başka kod blokları da çağrılabilir — tıpkı yukarıdaki completion handler görselinde gördüğümüz gibi!

İşte bu sayede, çalışması uzun sürecek olan fonksiyonları çağırıp, bitmesini beklemeden başka kod bloklarını geçebilir, fonksiyonun işi bittiğinde ise completion handler sayesinde fonksiyonun bize döndürdüğü değerlerle birtakım işlemler yapabiliriz.

Şimdiye kadar konuştuklarımız, oldukça soyuttu. Gelin birlikte somut bir örneğe bakıp completion handler bloklarının kodunu inceleyelim! 💪🏻

Completion Handler Nasıl Kodlanır?

Bu yazımızda completion handler koduna odaklanabilmek adına, küçük küçük kod bloklarından oluşan iki örnek inceleyeceğiz. İlk olarak completion handler kodunun genel formülüne bakalım:

“Closure” bloklarının genel şekli (Kaynak: Apple dokümantasyonu).

Normal bir fonksiyona benzer şekilde, completion handler bloklarının parametreleri, bir “return” tipi ve gövde kısmında birtakım kod ifadeleri vardır.

Şimdi gelin bu boşlukları doldurunca completion handler bloğumuzun neye benzediğine bakalım! 😁

İnceleyeceğimiz ilk örnek, ekrana yeni bir “UIViewController” elemanı getirmek için kullanılan present(_:animated:completion:) metodu. Apple dokümantasyonunda bu metodun tanımı aşağıdaki gibidir:

“present” metodunun tanımı (Kaynak: Apple dokümantasyonu).

Gördüğümüz üzere, bu metod parametre olarak bir completion handler bloğu kabul ediyor. (İstediğimiz herhangi bir metoda completion handler ekleyebiliriz, ancak bu her zaman anlamlı olmayabilir.) Gelin bu completion handler bloğunu yazalım!

present metodumuzun completion handler kod bloğu.

present metodu, firstVC ekranımızdan, secondVC ekranına geçiş yapmamızı sağlıyor. Metodun completion parametresi sayesinde ise metodun çalışması bittiğinde çağrılacak olan completion handler bloğunu tanımlayabiliyoruz.

Bu örneğimizde completion handler bloğumuz oldukça sade: Herhangi bir parametresi veya “return” tipi yok. Bunu () ve Void ile ifade ediyoruz. Completion handler bloğunun gövde kısmında ise sadece bir print ifadesi var. Böylece ikinci “ViewController” ekranımız ekrana yansıtıldıktan sonra, print ifadesi çağrılacak.

İkinci bir örnek ise daha sık göreceğimiz bir örnek: URLSession. Bu yazımızda “URLSession” kavramının detaylarına girmeyip sadece completion handler bloğuna odaklanacağız, ancak dilerseniz URLSession makalemizden bu konuda daha çok bilgi alabilirsiniz.

İnternetten veri çekmemizi sağlayan dataTask fonksiyonunun tanımı işte aşağıdaki gibidir:

“dataTask” fonksiyonunun tanımı (Kaynak: Apple dokümantasyonu).

Gördüğümüz gibi, önceki örneğimiz aksine bu örneğimizde completion handler bloğu üç farklı parametre kabul ediyor: Data , URLResponse , ve Error . Bu üç parametre fonksiyon çağrıldığında bize verinin çekilip çekilemediği hakkında çeşitli bilgiler verecek. Böylece completion handler bloğumuzda bu bilgileri kullanarak uygun işlemleri gerçekleştirebileceğiz.

Completion handler kod bloğumuz işte böyle gözükecek! (Aşağı yukarı diyelim — bazı kısımları URLSession konusunda çok detaya girdiğinden atladık.) 😊

“dataTask” fonksiyonumuzun completion handler kod bloğu.

Gördüğümüz gibi, completion handler bloğumuzda üç parametremizi alıp uygun işlemleri gerçekleştirmek için kullanıyoruz. Bu durumda uygun işlemler, verinin çekilip çekilmediğini kontrol etmek ve eğer başarılıysa veriyle birtakım işlemler yapmak oluyor.

Not: Fark ettiyseniz bu kodumuzda, -> Void kısmı yok. Eğer completion handler bloğunuzun bir “return” tipi yoksa, bu kısmı atlayabilirsiniz!

Böylece completion handler kod bloklarının iOS uygulamalarında kullanıldığı iki örneği incelemiş olduk! 🥳

Bu yazımızda completion handler yapısının ne olduğunu, ne zaman kullanıldığını ve nasıl kodlandığını öğrendik. Umarım keyifli bulmuşsunuzdur! Completion handler, Swift kodu yazarken birçok zaman işinize yarayacak bir kavramdır — yakın bir zamanda kullanacağınıza eminim. Keyifli kodlamalar! 💻 👋

Swift Öğrenin. Uygulama Geliştirin. Sınırların Ötesine Geçin.

Hem kod yazmaya yeni başlayanların hem de profesyonellerin rahatlıkla takip edebilecekleri 40 saatlik videolu eğitim ile Swift programlama dilini derinlemesine keşfedin. Eğitim boyunca karşılaşacağınız problemleri birebir online görüşmelerde çözün.

Bizi daha yakından takip etmek istiyorsanız, sosyal medya hesaplarımıza aşağıdan ulaşabilirsiniz!

Twitter | Instagram | Facebook

--

--