iOS Uygulama Geliştirme 3: Swift vs Objective-C

By -

Swift ile birlikte özellikle iOS uygulama geliştirmeye yeni başlamayı düşünen pek çok kişinin kafası karıştı. iOS uygulama geliştiricileri de Swift öğrenip öğrenmemek konusunda kararsız. Bu yazıda biraz fikir verebilmek adına Objective-C ve Swift’i çeşitli açılardan karşılaştırdım.

Tarihçe

Objective-C

Objective-C’yi geliştiren Brad Cox

Her köşeden başka bir nesneye yönelimli programlama (NYP) dilinin fırladığı günümüzün aksine 1970’lerin sonu, 1980’lerin başında en yaygın ve kullanılabilir NYP dili Smalltalk’du. NYP’ya duyulan ihtiyacın artması ve kullanımının yaygınlaşmasıyla birlikte çeşitli bilim adamları dönemin ve günümüzün en popüler programlama dili olan C’ye NYP mantığını eklemek için kolları sıvadılar. Danimarkalı bilgisayar bilimci Bjarne Stroustrup C++’ı geliştirirken Brad Cox’da 1982’de Objective-C’yi geliştirmeye başladı. Cox ve iş arkadaşı Tom Love uzun çalışmalar sonucu 1986’da Objective-C’yi resmi olarak yayınladılar.

Bu sırada 1985’de Apple’dan kovulan Steve Jobs, NeXT isimli bir şirket kurmuş ve NeXTstep isimli bir bilgisayar üretmeye çalışıyordu. NeXT mühendisleri NeXTstep’de çalışacak işletim sistemini Objective-C ile yazmaya karar verdiler ve oluşturdukları kütüphanelerde ön ek olarak bilgisayarın ismine ithafen “NS” kısaltmasını kullandılar. Zaman içinde bu kütüphanelerde çok büyük değişiklikler olsa da “NS” kısaltması sabit kaldı.

1990’lara gelindiğinde Apple pazar payını kaybetmeye başlamıştı; Mac OS beklentileri artık karşılayamıyordu. Apple yeni işletim sistemi projeleri başarıya ulaşamayınca 1996’da NeXT’i satın aldı ve Mac OS X, NeXT’in tecrübesi ve kütüphaneleri dolayısıyla Objective-C ile geliştirilmeye başlandı. Objective-C OS X’in temelini oluşturması nedeniyle Apple içerisinde kalıcı hale geldi. Apple 2006 yılında çeşitli özellikler eklediği Objective-C 2.0’ı yayınladı ve iOS’da da Objective-C’yi ana programlama dili olarak belirledi.

Swift

Swift WWDC 2014’de duyuruldu

Swift’in tarihçesi doğal olarak epey kısa; dil Apple’da geliştirici araçları biriminde çalışan (ve daha sonra bu birimin başına geçen) Chris Lattner‘ın emeğinin sonucu. 2010 yılında gizlice Swift’i geliştirmeye başlayan Lattner dilin temel özellikleri çalışır hale geldiği 2011 yılında Apple’daki üstlerine sırrını açıklıyor ve ardından kısa bir süre sonra Swift üzerinde çalışan ekip büyüyor. Şirket içinde yürütülen yaklaşık 2.5 yıllık gizli çalışmanın ardından da Swift geliştiricilere duyuruluyor.

Sözdizimi Farklılıkları

Objective-C çok uzun süredir farklı sözdizimi yüzünden eleştiri oklarının hedefi olmuş durumda. Özellikle C# veya Java gibi modern dillere alışmış programcılar için Smalltalk ve C’nin birleşiminden doğan söz dizimi tam bir kabus. Kısa (ve aslen kullanışsız) bir örnekle incelersek;

NSArray * dizi = [[NSArray alloc] initWithArray: @[@"Selam", @"Koddit"] copyItems: NO];

Görüldüğü üzere tek bir satır içerisinde “*”, “[]”  ve “@” gibi yabancı gözüken ve alışık olmayanlar için okumayı zorlaştıran pek çok karakter var. Swift ise Objective-C’ye nazaran daha “tanıdık” bir söz dizimine sahip. Benzer bir örneğe bakarsak;

let dizi = Array<String>(count: 5, repeatedValue: "Koddit");

Her ne kadar Swift’de kod okumak daha kolay gibi dursa da işin asıl pek öyle değil. Mesela Apple’ın resmi Swift dökümanında geçen aşağıdaki kodu “optional” ve “optional chaning” kavramları konusunda fikriniz yoksa doğru bir şekilde anlamanız epey zor;

if let johnsStreet = john.residence?.address?.street {
    println("John's street name is \(johnsStreet).")
} else {
    println("Unable to retrieve the address.")
}

Ayrıca kavram konusunda fikriniz olsa bile hem Objective-C hem Swift’de karışık gelecek bazı söz dizimleri de mevcut. Örneğin pek çok programcı closure kavramına aşina olsa da hem Objective-C hem de Swift‘de closure söz dizimi epey karmaşık.

Özetle Swift başta daha “arkadaş canlısı” gözükse de diğer dillere göre garip ve yabancı pek çok noktası da mevcut.

Yetenekler

Swift genç bir dil olması sayesinde Objective-C’ye oranla daha yetenekli; geliştiriciler diğer dillerde bulunan ve sevilen özellikleri bir araya toplamış. Bir fonksiyondan birden çok değer döndürme (Tupple), değişken tanımlarken her seferinde tipini yazmaya gerek olmaması (Type Inference), Class-Struct-Enum içerisinde başka Class-Struct-Enum tanımlayabilme (Nested Types), +, -, *, / gibi standart operatörleri kendi tanımlarının dışında kullanabilme (Operator Overloading) ve hatta kendi operatörünü tanımlama gibi Objective-C’de olmayan pek çok özellik dile eklenmiş.

Yapacağınız işe bağlı olarak Objective-C’de de pointerlara doğrudan erişilebiliyor olması ve preprocessor komutları hayatınızı baya kolaylaştırabilir ama bunları gerçekleştirmenin de Swift’de çeşitli yolları mevcut.

Esneklik

Swift kod yazma sırasında Objective-C’ye göre çok daha esnek. Apple’ın resmi dökümantasyonunda neredeyse her konu için “isterseniz böyle de yazabilirsiniz” şeklinde bir örnek var. Mesela aşağıdaki 4 satır da String’lerden oluşan bir dizi tanımlıyor;

let dizi = [String]();
let dizi2 = Array<String>()
let dizi3: [String] = Array<String>();
let dizi4: Array<String> = [String]()

Elbette Objective-C’de de diziyi birden çok şekilde tanımlamak mümkün ama Objective-C’de farklılıklar genel olarak söz diziminden değil farklı metotların çağrılmasından kaynaklanıyor. Bu arada örnek kodda noktalı virgülün bazı satırlarda olmaması da hata değil, noktalı virgül kullanımı JavaScript gibi Swift’de de isteğe bağlı.

Swift söz diziminin esnekliği konu closure’lar olunca daha net ortaya çıkıyor. Aşağıdaki 6 örnek de Apple’ın Swift dökümanında bulunuyor ve tahmin edeceğiniz üzere hepsi aynı işi yapıyor;

reversed = sorted(names, { (s1: String, s2: String) -> Bool in
    return s1 > s2
})
reversed = sorted(names, { s1, s2 in return s1 > s2 } )
reversed = sorted(names, { s1, s2 in s1 > s2 } )
reversed = sorted(names, { $0 > $1 } )
reversed = sorted(names, >)
reversed = sorted(names) { $0 > $1 }

Swift hem Objective-C ile uyumluyken hem de Objective-C’nin desteklemediği pek çok yeni özelliği destekliyor, dolayısıyla bu da programcıya söz dizimi dışında da bir esneklik sağlıyor. Buna en güzel örnek olarak generic kullanımı verilebilir;

func koddit (değişken: Any) -> Bool { 
    if değişken is String {
        return true;
    } else {
        return false;
    }
}
func kodditGeneric<T>(değişken: T) -> Bool {
    if değişken is String {
        return true;
    } else {
        return false;
    }
}

“Any” ve “AnyObject” Objective-C ile uyumluluk açısından Swift’e eklenen ve her nesnenin atanabileceği veri tipleri. Generic ise benzer amaçlarla kullanılan ve kısmen daha esnek olan bir yapı. Ancak bir kısıtlama olmadığı için ikisini bir arada kullanmak mümkün. (Ek olarak belirteyim,  değişken adı olarak “değişken”‘i kullanmam yanlış değil, Swift Unicode karakterleri desteklediği için değişken isimlerinde Türkçe veya emoji karakterleri kullanılabiliyor)

Her ne kadar esneklik güzel bir şey gibi görünse de eğer başkalarının kodlarıyla sık sık haşır neşir oluyorsanız veya kalabalık bir grupla belirli kodlama standartı olmadan çalışıyorsanız başınızı çok büyük ihtimalle ağrıtacaktır.

Hata Önleme ve Ayıklama

Küçük hatalar bazen büyük sıkıntılar yaratabiliyor.

Derleyici ve IDE’ler her ne kadar zeki olsalar da bazen programcıların yaptığı küçük hataları farkedemeyebiliyorlar. Genelde bunlar çok büyük bir soruna neden olmasalar da Apple’ın goto fail; rezaletinde olduğu gibi ciddi sonuçları da olabiliyor. Swift geliştirilirken de bu hataları azaltmak adına pek çok önlem alınmış;

  • If-Else blokları süslü parantez ile kullanılmak zorunda.
  • Switch-Case bloklarında tüm durumlar tanımlanmalı.
  • Switch-Case bloklarında her durum için ayrı ayrı “break” yazmaya gerek yok, bunun yerine eğer kodun sonraki duruma devam etmesi isteniyorsa özellikle belirtiliyor.
  • Eğer mantıksal bir kontrol her zaman doğru veya yanlışsa derleyici hata veriyor.
  • Değişkene atama yapmadan veya tip uyumsuzluğunda değişkeni kullanmak mümkün değil.
  • Eğer işlem sırasında sayılarda taşma olursa program hiç bir şey olmamış gibi devam etmek yerine sonlanıyor.
  • Değişkenin “NULL” (Swift ve Objective-C’deki karşılığı “nil”) olup olamayacağı düşünülerek değişkenler farklı tanımlanıyor.

Bunlar kağıt üzerinde çok güzel gözükse de ne yazık ki özellikle tip uyumsuzluğu durumunda derleyicinin verdiği hatalar çoğu zaman bir şey ifade etmiyor. Küçük bir şey yazarken bile ” Cannot convert expression’s type ‘($T1, $T2, $T3) -> $T0’ to type ‘()’ ”  gibi manasız hataların karşınıza çıkması olası.

Diğer bir sıkıntı da Xcode ve Swift’in halen tam olarak anlaşamıyor olması. Xcode Swift’i yeniden düzenleyemediği gibi (değişken adını kolayca değiştirmek vs) hata ayıklarken de pek yardımcı olmuyor. Objective-C’nin aksine basit bir değişken değerini görmek için bile lldb komutlarını kullanmak veya fazladan kod yazmak açıkcası epey sinir bozucu.

Performans

Apple’a göre Swift’in hız karşılaştırması

Apple Swift’in Objective-C’ye göre çok daha hızlı olduğunu iddia ediyor. Henüz bunu kesin olarak doğrulayan bir bulgu olmamakla birlikte Swift 1. sürümüyle birlikte basit testlerde yaklaşık aynı hızlarda sonuçlar veriyor, zaten teorik olarak da Objective-C’nin çalışma şekli nedeniyle Swift’in biraz daha hızlı olması normal. Benim çeşitli project euler sorularında yaptığım denemelerde Swift genelde daha yavaş kalsa da yaptığımın çok ciddi bir test olmadığını da belirtmem gerekiyor.

Bu arada eğer uygulamanızda Apple kütüphanelerini sıkça kullanıyorsanız Swift veya Objective-C kullanmanız performans açısından pek bir fark yaratmayabilir, Apple Swift için bazı düzenlemeler yapsa da kütüphanelerinde genel olarak C, C++ ve Objective-C kullanıyor.

Hangisini Öğrenmeli

Hangi dili öğreneceğiniz tamamen sizin planlarınızla ile alakalı. Objective-C söz dizimi biraz korkutucu gözükse de Swift’in özelliklerini ve püf noktalarını öğrenmek çok daha zor. Diğer yandan zaten iOS’a veya OS X’e nasıl uygulama geliştireceğinizi öğrenirken vaktinizin büyük kısmını Apple kütüphanelerini öğrenerek harcayacaksınız.

BENCE eğer kendi uygulamanızı yazmak istiyorsanız ve yeterli vaktiniz varsa Swift öğrenin. Vaktiniz kısıtlıysa veya bir firmaya girmek ve iOS / OS X üzerine çalışmak istiyorsanız Objective-C öğrenmeniz daha mantıklı olacaktır.

Sonuç

Swift de Objective-C de mükemmel değil. Swift 2010’da geliştirilmeye başlamasının etkisiyle daha modern çözümler sunmakla birlikte Objective-C de hem iOS ve OS X’in merkezinde olması hem de geliştiriciler tarafından yaygın kullanımı nedeniyle uzun bir süre daha sektörde önemli bir yere sahip olacak.

Yüksek lisanstan vakit bulabildiğinde iOS uygulama geliştirmekle ilgili bildiklerini yazmaya çalışıyor.