Swift 2 ile Hata Yönetimi (Error Handling) yazısı ilk önce Koddit üzerinde ortaya çıktı.
]]>var hata: NSError?
let dosya = NSFileManager.defaultManager().contentsOfDirectoryAtPath("/Users/Koddit", error: &hata)
if let hata = hata {
// Hata oluştu
} else {
// Sıkıntı yok, içeriği kullan.
}
Bu yaklaşımdaki en büyük sorun NSError nesnesinin kontrol edilip edilmediğini derleyicinin takip edemiyor olması. Programcı basit bir kontrolü atladığında daha önce testlerde yaşanmayan ve pek beklenmeyen bir durumda uygulamanın patlaması çok olası. Apple Swift 2 ile bunun önüne geçmek için NSError‘ün bu kullanımı kaldırarak daha bilindik try-catch yapısını dile ekliyor. Aynı kodu Swift 2 ile yazarsak;
do {
let dosya = try NSFileManager.defaultManager().contentsOfDirectoryAtPath("/Users/Koddit")
// Sıkıntı yok, dosyayı kullan.
} catch {
// Hata oluştu
}
Böylece hem kod kısa kısaldı hem de programcı olarak hata yapma olasılığınız neredeyse ortadan kalktı. Ancak ve lakin başta da belirttiğim gibi NSError tek yöntem değil. Çoğu kişi kendi kodunda NSError ile uğraşmak yerine dönen değeri kontrol etmeyi veya daha karışık ve projeye özel yapılar kullanmayı tercih ediyor ki bu herkes için tam bir kaos. Özellikle başkasının kodunu kullandığınız durumlarda yanlış şeyler yapmanız veya bir şeyleri atlamanız çok olası. Pek kullanışlı olmayan ancak basit bir örneğe göz atarsak;
func böl (bölünen: Int, bölen: Int) -> Int?
{
if (bölen == 0 ) {
return nil;
}
return bölünen / bölen;
}
if let sonuç = böl (3, bölen: 1 ){
// Sonucu kullan
}
Fonksiyon eğer bölen 0 ise nil, değilse bölme işleminin sonucunu döndürüyor. Ancak geriye nil dönmesi kodu ilk kez kullanan kişi açısından pek yararlı değil, eğer dokümantasyon da yoksa niye nil döndüğünü anlaması için kodu okuması şart. Elbette geriye hata mesajı döndürmek vs. gibi olaylara girilebilir ancak bunlar da kodun iyice dağılmasına ve karışık hale gelmesine sebep olabilir. Swift 2 neyse ki bizi bu tarz dertlerden kurtarıyor;
enum BölmeHatası: ErrorType
{
case BölenSıfır;
}
func böl (bölünen: Int, bölen: Int) throws -> Int
{
if (bölen == 0) {
throw BölmeHatası.BölenSıfır;
}
return bölünen / bölen;
}
do {
let sonuç = try böl (3, bölen: 1);
// Sonucu kullan
} catch BölmeHatası.BölenSıfır {
// Bölen sıfır olduğu için hata oluştu.
}
ErrorType Swift 2 ile gelen yeni bir protokol, catch ile yakaladığımız hataların bu protokolü desteklemesi gerekiyor. Bölme sırasındaki olabilecek hataları tanımladıktan sonra fonksiyonu “throws” olarak tanımlıyoruz ve hataların oluştuğu noktalarda “throw” kelimesi ile ilgili hataları fırlatıyoruz. Önceki örneğe göre biraz daha fazla kod içerse de bu şekilde yazmak hem daha temiz hem daha değişikliklere açık.
O zaman temel yapıdan bahsettiğimize göre yeni yöntemin yararlarını anlayabilmek için önce daha karışık bir örnekten yola çıkarak koda önce klasik hata düzeltme yöntemlerini eklemeyi deneyelim ve daha sonra Swift 2’ye dönüştürelim;
func suParasınıYatır (miktar miktar: Int) -> Int?
{
if (!sorguBaşlat()) {
return nil;
}
if let kullanıcıBorcu = borçSorgula() where kullanıcıBorcu <= miktar
{
if (!işlemiOnayla ()) {
return nil;
}
sorguBitir(); // False dönse de işlem bitti.
return miktar - kullanıcıBorcu; // Para üstü
}
sorguBitir(); // False dönse de işlem zaten iptal.
return nil;
}
func sorguBaşlat () -> Bool {
// Bu fonksiyonun database e bağlantı kurmak / session başlatmak
//gibi işlemler yaptığını hayal edin.
// Bunları yapamadığında geriye false dönüyor.
return false;
}
func sorguBitir () -> Bool {
// Bu fonksiyonun database le olan bağlantıyı kapatmak / session'ı
//sona erdirmek gibi işlemler yaptığını hayal edin.
// Bunları yapamadığında geriye false dönüyor.
return false;
}
func borçSorgula () -> Int?
{
// Eğer fatura ödenmediyse miktarı döndür.
if (sonFaturaÖdenmişMi()) {
return nil;
}
return 150; // Bunun sistemden döndüğünü hayal edin.
}
func sonFaturaÖdenmişMi () -> Bool
{
// Sisteme son borcu sor
return false; // Bunun sistemden döndüğünü hayal edin.
}
func işlemiOnayla () -> Bool {
// Sisteme parayı aktardığını ve borcu sildiğini hayal edin.
// Bunları yapamadığında geriye false dönüyor.
return true;
}
if let sonuç = suParasınıYatır(miktar: 50) {
// Para başarıyla yatırıldı.
} else {
// Para yatırılamadı.
}
Bu hayali tahsilat programında kullanıcı su parasını ödemek istediğinde öncelikle suParasınıYatır fonksiyonu çalışıyor ve gerekli bağlantıları oluşturuyor, ardından sisteme kullanıcının borç miktarını soruyor ve işlemi onaylıyor, hepsi sona erince de bağlantıları bitirip para üstünü geriye döndürüyor. Herhangi bir sıkıntı oluştuğu anda ise tüm fonksiyonlar nil döndürüyor ki bu büyük bir problem, kullanıcıya bu durumda neyin yanlış gittiğini aktarmanız veya programcı olarak kullanıcıya çaktırmadan bunları halletmeniz mümkün değil.
Eğer koda Swift 2 öncesindeki gibi bir hata yönetimi yaparsak yaklaşık şöyle bir kod elde ederiz;
var birşeylerTersGitti = false; // Sahte hata oluşturmak için, yok sayabilirsiniz.
func suParasınıYatır (miktar miktar: Int) -> (paraÜstü: Int, hataMesajı: String?)
{
var hata: NSError?;
var paraÜstü: Int = 0, hataMesajı: String?;
sorguBaşlat(&hata);
if (hata != nil) {
hataMesajı = hata!.localizedDescription;
} else {
let borçMiktarı = borçSorgula(&hata);
if (hata != nil) {
hataMesajı = hata!.localizedDescription;
} else if borçMiktarı <= miktar {
işlemiOnayla (&hata);
if (hata != nil) {
hataMesajı = hata!.localizedDescription;
} else {
paraÜstü = miktar - borçMiktarı;
}
} else {
let eksik = borçMiktarı - miktar; // Türkçe karakter sorunu yüzünden sonraki satırda " " içerisinde değil, orada kullanabilirsiniz.
hataMesajı = "\(eksik)" + " TL eksik.";
}
sorguBitir(&hata);
if (hata != nil) {
// Yeniden dene?
// PS: İşlem zaten sona erdi o yüzden hatayı göndermeye gerek yok.
}
}
return (paraÜstü, hataMesajı);
}
func sorguBaşlat (error: NSErrorPointer) {
// Bu fonksiyonun database e bağlantı kurmak / session başlatmak
// gibi işlemler yaptığını hayal edin.
if (birşeylerTersGitti) {
hataOluştur(error, hataMesajı: "Sorgu başlatılırken zaman aşımı oldu.", kod: 101)
}
}
func sorguBitir (error: NSErrorPointer) {
// Bu fonksiyonun database le olan bağlantıyı kapatmak / session'ı
//sona erdirmek gibi işlemler yaptığını hayal edin.
if (birşeylerTersGitti) {
hataOluştur(error, hataMesajı: "Sorgu sonlandırılırken zaman aşımı oldu.", kod: 101)
}
}
func borçSorgula (error: NSErrorPointer) -> Int
{
// Eğer fatura ödenmediyse miktarı döndür.
if (sonFaturaÖdenmişMi()) {
hataOluştur(error, hataMesajı: "Ödenmemiş borç bulunamadı.", kod: 102)
return 0;
}
return 150; // Bunun sistemden döndüğünü hayal edin.
}
func sonFaturaÖdenmişMi () -> Bool
{
// Sisteme son borcu sor
return false; // Bunun sistemden döndüğünü hayal edin.
}
func işlemiOnayla (error: NSErrorPointer) {
// Sisteme parayı aktardığını ve borcu sildiğini hayal edin.
// Bunları yapamadığında geriye false dönüyor.
if (birşeylerTersGitti) {
hataOluştur(error, hataMesajı: "İşlem onaylanamadı, sistemde arıza var.", kod: 103)
}
}
func hataOluştur (error: NSErrorPointer, hataMesajı: String, kod: Int)
{
let userInfo = [NSLocalizedDescriptionKey: hataMesajı];
if error != nil {
error.memory = NSError(domain: "Koddit", code: kod, userInfo: userInfo);
}
}
let sonuç = suParasınıYatır(miktar: 50);
if sonuç.hataMesajı != nil {
print (sonuç.hataMesajı!);
// Para yatırılamadı.
} else {
// Para yatırıldı.
}
Kodun anlaşılır olması çok önemli
Artık neyin ters gittiğini bilsek de sürekli olarak NSError ile uğraşmak zorundayız, özellikle suParasınıYatır fonksiyonunun içi korkunç. Hele hele daha farklı hata mesajları veya hata mesajına göre işlemler yapmak istediğinizde kodun iyice içinden çıkılamaz bir hale gelmesi çok olası. Elbette bu kod en ideali değil ve iyileştirmek için bir şeyler yapılabilir ancak Swift 2 öncesi genel olarak takip edeceğiniz yol da bu. (NSError kullanmazsanız her fonksiyondan hata kodu veya nil döndürüp onları kontrol edebilirsiniz veya kendi hata sınıflarınızı oluşturabilirsiniz). Peki Swift 2’de bu çok mu farklı? try-catch’in o kadar ciddi bir katkısı var mı? Kendiniz karar verin;
var birşeylerTersGitti = false; // Sahte hata oluşturmak için, yok sayabilirsiniz.
/// 1 - Enumlar
enum SistemHatası: ErrorType
{
case ZamanAşımı, SistemArızası
}
enum ÖdemeHatası: ErrorType
{
case BorçYok, ParaYetersiz (Int)
}
/// 3 - Ana Fonksiyon
func suParasınıYatır (miktar miktar: Int) throws -> Int
{
/// 5 - Defer
defer {
do {
try sorguBitir ();
} catch {
// Yeniden dene?
// PS: İşlem zaten sona erdi o yüzden hatayı göndermeye gerek yok.
}
}
try sorguBaşlat ();
let borçMiktarı = try borçSorgula();
if (borçMiktarı > miktar) {
throw ÖdemeHatası.ParaYetersiz(borçMiktarı - miktar);
}
return miktar - borçMiktarı;
}
/// 2 - Yan Fonksiyonlar
func sorguBaşlat () throws {
// Bu fonksiyonun database e bağlantı kurmak / session başlatmak
// gibi işlemler yaptığını hayal edin.
if (birşeylerTersGitti) {
throw SistemHatası.ZamanAşımı;
}
}
func sorguBitir () throws {
// Bu fonksiyonun database le olan bağlantıyı kapatmak / session'ı
// sona erdirmek gibi işlemler yaptığını hayal edin.
if (birşeylerTersGitti) {
throw SistemHatası.ZamanAşımı;
}
}
func borçSorgula () throws -> Int
{
// Eğer fatura ödenmediyse miktarı döndür.
if (sonFaturaÖdenmişMi()) {
throw ÖdemeHatası.BorçYok;
}
return 150; // Bunun sistemden döndüğünü hayal edin.
}
func sonFaturaÖdenmişMi () -> Bool
{
// Sisteme son borcu sor
return false; // Bunun sistemden döndüğünü hayal edin.
}
func işlemiOnayla () throws {
// Sisteme parayı aktardığını ve borcu sildiğini hayal edin.
// Bunları yapamadığında geriye false dönüyor.
if (birşeylerTersGitti) {
throw SistemHatası.SistemArızası;
}
}
///4 - Fonksiyonun kullanımı
do {
try suParasınıYatır (miktar: 50);
} catch ÖdemeHatası.BorçYok {
print ("Borç yok");
} catch ÖdemeHatası.ParaYetersiz (let miktar) {
print ("\(miktar)" + " TL eksik");
} catch is SistemHatası {
print ("Sistemde sorun oluştu");
// Tekrar dene ?
}
Peki hata düzeltmeyle ilgili bilinmesi gereken başka neler var?
let dosyaİçeriği = try! NSFileManager.defaultManager().contentsOfDirectoryAtPath("/Users/Koddit")
enum DeğerHatası: ErrorType
{
case İsim, Adres;
}
struct Mağaza {
var isim: String!;
var adres: String!;
}
func mağazaOluştur (veri: [String: String]) throws -> Mağaza
{
guard let isim = veri ["isim"] else {
throw DeğerHatası.İsim;
}
guard let adres = veri ["adres"] else {
throw DeğerHatası.Adres;
}
return Mağaza(isim: isim, adres: adres);
}
do {
var mağaza = try mağazaOluştur (["içerik" : "yiyecek"]);
} catch DeğerHatası.İsim {
print ("İsim eksk");
} catch DeğerHatası.Adres {
print ("Adres eksik");
}
Son not: Yazıdaki ilki hariç tüm kod parçalarını Xcode 7 Playgrounds ile deneyebilirsiniz. Ayrıca Koddit’in kod editörü Swift için Türkçe karaktere izin vermediği için kod örneklerinin çoğunu Swift yerine XHTML ile işaretlemek durumunda kaldım, renksiz oldu biraz kusura bakmayın.
Swift 2 ile Hata Yönetimi (Error Handling) yazısı ilk önce Koddit üzerinde ortaya çıktı.
]]>iOS Uygulama Geliştirme 3: Swift vs Objective-C yazısı ilk önce Koddit üzerinde ortaya çıktı.
]]>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 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.
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.
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.
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.
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ış;
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.
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.
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.
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.
iOS Uygulama Geliştirme 3: Swift vs Objective-C yazısı ilk önce Koddit üzerinde ortaya çıktı.
]]>iOS Uygulama Geliştirme 2: Nereden Öğrenmeli, Nereleri Takip Etmeli? yazısı ilk önce Koddit üzerinde ortaya çıktı.
]]>
Ray Wenderlich kendi halinde iOS dersleri yazan bir yazılımcıyken bloğu zamanla popüler hale gelir, isteklere yetişemez, yardımcı yazarlar alarak siteyi büyütmeye başlar ve olaylar gelişir. Muhtemelen hiç bir fikri olmayıp iOS ve Objective-C’ye balıklama dalmak isteyenler için raywenderlich.com en iyi kaynak. Sitede hem programlamaya yeni başlayanlara hem de özel bir konuda kendini geliştirmeye çalışanlara uygun dersler mevcut. Ayrıca dileyenler için video dersler de mevcut ancak videolara erişebilmek için aylık veya yıllık üyelik gerekiyor.
Apple gerçekten detaylı ve düzgün anlatımlı bir kütüphaneye sahip. Eğer iOS uygulamalarının arka yapısıyla ilgili hiç bir fikriniz yoksa ve vaktiniz varsa Apple’ın “Bugün iOS Uyulaması Geliştirmeye Başlayın” dökümanını okuyarak işe başlayabilirsiniz. Bu kütüphaneden iOS’la ilgili temel frameworklerden düşük seviye görüntü işlemeye kadar her konuda istemeyeceğiniz kadar detaylı bilgiyi elde etmek mümkün, bir konuda uğrşamaya başlamadan önce alakalı dökümanı bulup okumanızı şiddetle tavsiye ederim. Dökümantasyonun tek eksi sayılabilecek yanı kısmen ağdalı bir dille yazılmış olması ancak ona da zamanla alışılıyor.
Eğer dersleri okumak yerine dinlemeyi/izlemeyi tercih ederseniz Stanford Üniversitesi’nin verdiği iOS programlama dersleri uzunca bir süredir popüler. Bu derslere iTunesU üzerinden ücretsiz olarak erişmek mümkün. Eğer geliştirici hesabınız varsa Apple’ın geliştirici platformu üzerinden sunduğu videolar arasında da hem yeni başlayanlara, hem de eski geliştiricilere hitap edecek videolar var. Özellikle WWDC konferansları güncel teknolojileri takip etmek ve yeni bakış açıları kazanmak için oldukça yararlı. Ayrıca YouTube’da da istemeyeceğiniz kadar Objective-C ve Swift dersi bulabilirsiniz, ama bunların pek çoğunun fazlasıyla kalitesiz olduğunu ve hatta kafanızı karıştırabileceğini aklınızdan çıkarmayın.
Piyasada iOS geliştirmeyle ilgili onlarca kitap mevcut. Her sene yeni bir iOS sürümünün çıkması ve bunlarda irili ufaklı onlarca şeyin değişmesi kitapların da her sene yeni bir verisyonunun çıkmasını gerektiriyor. Dolayısıyla kitap seçerken en çok dikkat edilmesi gereken konu iOS’un güncel sürümünü kapsayıp kapsamadığı.
Ne yazık ki Türkçe kitapların bildiğim kadarıyla pek çoğu yazıldığı iOS sürümlerinde kalıp güncellenmemiş durumda. Eğer iOS programlamaya Türkçe kitaplar ile başlamak istiyorsanız iOS yerine Objective-C’yi konu alan kitaplara yönelmeniz daha mantıklı olacaktır.
Yabancı yayınlara gelince; O’Reilly yayınlarından çıkan “Cookbook” serisindeki kitaplar genel olarak ele aldığı konuyu detaylı ve akademik (ancak kısmen sıkıcı) şekilde inceliyorlar. Apress yayınlarından çıkan kitapların da zaman zaman biraz yüzeysel kalsalar da yeni başlayanlara uygun, örnek ağırlıklı güzel bir anlatımı var. Bunların dışında Packt yayınlarının iOS ile ilgili kitapları da incelenebilir. Piyasada bunların dışında da başlangıç düzeyinde ve ileri düzeyde pek çok kaynak elbette mevcut.
Son olarak bu kitapların neredeyse hepsinin e-kitap formatında da mevcut olduğunu eklemiş olayım
İnternette hem Objective-C/Swift öğrenirken yararlanabileceğiniz hem de takip etmenin size ummadığınız bir şeyler katabileceği çeşitli siteler var. Bunları detaylarına girmeden sıralarsam;
Artık güncellenmeyen ama kurcalamanın faydalı olacağını düşündüğüm bazı siteler: idev101, cocoadevcentral, cocoawithlove, theocacao.
Düzenli olarak güncellenen ve takip etmenin yararlı olacağı siteler: NSHipster, natashatherobot, petersteinberger, maniacdev, iosdevelopertips, NSBlog, ios-blog.
Tüm bunların dışında StackOverflow‘da çok oy alan sorulara ve cevaplarına bakmak da daha sonradan beklemediğiniz anlarda işinize yarayacak bilgiler edinmenize yardımcı olabilir.
İnternette iOS uygulama geliştirmek isteyen biri için istemeyeceği kadar kaynak mevcut, ben de bu yazıda kendi bilip yararlandıklarımı olabildiğince paylaşmaya çalıştım. Swift ve Objective-C’yi karşılaştırdığım dizinin 3. yazısında görüşmek üzere.
iOS Uygulama Geliştirme 2: Nereden Öğrenmeli, Nereleri Takip Etmeli? yazısı ilk önce Koddit üzerinde ortaya çıktı.
]]>iOS Uygulama Geliştirme 1: Nereden Başlamalı, Ne ile Yazmalı? yazısı ilk önce Koddit üzerinde ortaya çıktı.
]]>iOS uygulama geliştirmeye başlamak isteyen ama Apple’a uzak olan kişiler genellikle ilk olarak “Windows üzerinde nasıl yapılır?” sorusunun cevabını merak eder. Konuyla ilgili epey doyurucu bir Stackoverflow sorusu hali hazırda mevcut. Eğer birden çok platforma destek vermek gibi bir derdiniz yoksa bence başlangıç için sanal makineye Mac OS kurmak en mantıklı seçenek.
Sık sorulan diğer bir soru da testler için iOS yüklü bir cihaza sahip olmanın gerekip gerekmediği. Hayır, iPod, iPhone veya iPad’iniz olasına gerek yok, Apple geliştirme ortamı olan Xcode ile birlikte gayet başarılı bir iOS simülatörü geliyor. Burada Android tecrübesi olanların tek kaşlarının havaya kalktığını görür gibiyim; evet simülatör gerçekten hızlı ve kullanılabilir durumda. Android emülatörleri cihazların CPU’sunu taklit etmeye çalışıyor, bu da çalışan her satır kodun bir kaç dönüşümden geçmesini gerektiriyor. iOS simülatörü ise daha yüzeysel davranarak doğrudan bilgisayarın CPU’sunu kullanıyor ve böylece daha akıcı bir kullanıcı deneyimi sağlıyor. iOS simülatörü ile yapamayacağınız çeşitli şeyler olsa da başlangıç için çok büyük bir sıkıntı yaratmayacaklardır.

Kafa karıştıran bir konu da Apple’ın geliştirici hesapları için 100$ gibi bir ücret istemesi. Mac ile uygulama geliştirilirken Apple’ın geliştirdiği IDE olan Xcode kullanılıyor ve Xcode AppStore’dan ücretsiz olarak indirilebiliyor. Geliştirici hesabınız olmaması Xcode’u indirmenize veya iOS simülatörünü kullanmanıza engel değil. Ama uygulamanızı cihaz üzerinde denemek ve AppStore’a yollamak için bu hesaba ihtiyacınız var. Eğer geliştirici hesabınız yoksa cihazınız üzerinde uygulamayı çalıştırmak için de çeşitli yollar var ancak bu yöntemler Jailbreak yapmayı gerektirdiği için pek tavsiye etmiyorum.
Mac OS X yüklü bir cihaz elde ettiniz ve Xcode’u kurdunuz. Şimdi ise muhtemelen kafanızdaki soru uygulamayı geliştirirken hangi programlama dilini kullanacağınız.
iOS uygulamalarının çok büyük bir kısmı Objective-C ile yazılıyor ama zaman zaman C++ ile C yardımcı olarak kullanılıyor. Bunun yanında OpenGL ile yazılan oyunların C++ kullandığını ve Unity’nin C# kodları çağırmaya izin verdiğini de eklemek lazım.
Objective-C ve C++ aslen iki kardeş dil olsa da yazım kuralları birbirlerinden epey farklı. C++ dünya genelinde her alanda yaygın bir kullanıma sahipken Objective-C bugüne kadar Apple’ın desteği ve biraz da zorlamasıyla hayatta kaldı. Bunun nedenlerinden biri C’den epey farklı bir söz dizimine sahip olmasıyken diğeri de dile gücünü veren kütüphanelerin çoğunlukla Apple cihazlarına bağımlı olması. Elbette başka sebepler de sayılabilir ancak hem diğer dilleri kullanan programcılar hem de programlamaya yeni başlayanlar Objective-C’yi öğrenmekte güçlük çekmekteydi. Programcıların şikayetlerini duyan Apple, 2 Haziran tarihindeki etkinliğinde modern söz dizimine ve pek çok özelliğe sahip yepisyeni bir programlama dilini, Swift’i tanıttı.
Kısaca elimizde 4 farklı dil var, C, C++, Objective-C ve Swift. Peki hangilerini bilmelisiniz?
Oyun yapmak istiyorsunuz veya uygulamanızın en önemli ve zorlu kısmı algoritması diyelim. Farklı işletim sistemleri için aylarca uyarlama yapıp programı baştan yazmak istemiyorsanız yönelmeniz gereken dil C++. C++ sayesinde performanstan ödün vermezken uygulamayı her işletim sistemi için sil baştan yazma derdinden de kurtulmuş olacaksınız. Ama yine de çoğu durumda iOS için bir miktar Objective-C (veya Swift) bilmeniz gerekeceğini unutmayın.
Güncelleme (30/12/14): Geçen zamanla birlikte bu yazının Swift mi Objective-C mi kısmı biraz geçersiz hale geldi. Ayrıntılı bilgi için Swift vs Objective-C konulu yazıma göz atabilirsiniz.
Başlangıç için Swift mi Objective-C mi sorusunun cevabı şu an için Objective-C. Öncelikle Swift halen “beta” bir programlama dili olduğu için pek çok hatası mevcut ve tüm özellikleri bile açıklanmış veya kullanılabilir durumda değil. Ayrıca Swift ile program yazabilmek için geliştirici hesabına sahip olmanız gerekiyor. Henüz yaklaşık 1 aydır ortalıkta olduğu için bir noktada takıldığınızda araştırabileceğiniz kaynak sayısı çok çok sınırlı. Ek olarak; Swift’in betası sona erene kadar yazacağınız uygulamaları AppStore’a yüklemeniz de mümkün değil.
Objective-C’ye dönersek; AppStore’daki 1.2 milyon uygulamanın çok büyük bir kısmı Objective-C ile yazılmış durumda olduğu için Objective-C kolay kolay yok olmayacak. 1 milyon uygulamada kullanılmış olması pek çok kaynağa sahip olduğu ve her türlü sorununuza doğru kelimelerle ararsanız çok büyük bir sıkıntı çekmeden çözüm bulabileceğiniz anlamına geliyor. Eğer iOS uygulama geliştirmeye devam edecekseniz eninde sonunda Objective-C’yle karşılaşacaksınız ve kodu anlamanız gerekecek. Diğer yandan Objective-C’de kullandığınız Apple kütüphanelerinin hepsi zaten Swift’de de mevcut olacağı için ilerde Swift’e geçmeniz gerekince sıkıntı da yaşamayacaksınız.
Objective-C ile birlikte zaman zaman C’de kullanılıyor. C’yi bilmeniz şart değil ancak C 101’i geçecek kadar bilmek pek çok durumda kodu daha iyi anlamanıza ve tasarlamanıza yardımcı olacaktır. Ben eğer Objective-C’ye başlamadan önce hiç bilmiyorsanız C’ye giriş derslerine de göz atmanızı öneririm.
Çok özetle tekrarlarsam Mac OS X yüklü bir bilgisayarınız varsa uygulama geliştirmeye hemen bugün Xcode yükleyerek başlayabilirsiniz. Eğer özel bir durum mevcut değilse, hızlıca çıkarmayı planladığınız ciddi bir uygulama fikriniz varsa veya mevcut projelerde de çalışmayı düşünüyorsanız (ki düşünmüyorsanız da beklemediğiniz bir anda gerçekleşebilir) halen Objective-C öğrenmek en mantıklı hareket olacaktır.
Yazının bir sonraki bölümünde görüşmek üzere.
iOS Uygulama Geliştirme 1: Nereden Başlamalı, Ne ile Yazmalı? yazısı ilk önce Koddit üzerinde ortaya çıktı.
]]>