Bir iOS Geliştirici Kılavuzu: Objective-C'den Learning Swift'e
Yayınlanan: 2022-03-112008'de Apple, iPhone SDK 2.0'ı duyurdu ve piyasaya sürdü. Bu olay, yazılım geliştirmede başka bir devrim başlattı ve yeni bir geliştirici türü doğdu. Artık iOS geliştiricileri olarak kabul ediliyorlar.
Bu geliştiricilerin çoğu daha önce Objective-C kullanmamıştı ve bu Apple'ın onlara attığı ilk zorluktu. Alışılmadık sözdizimine ve manuel bellek yönetimine rağmen, son derece başarılı oldu ve App Store'u on binlerce uygulamayla doldurmaya yardımcı oldu. Apple, her sürümde sürekli olarak Objective-C'yi geliştirdi, bloklar ve değişmez değerler ekledi, otomatik referans sayımı ile basitleştirilmiş bellek yönetimi ve modern bir programlama dilinin göstergesi olan diğer birçok özellik.
Ve 6 yıl boyunca Objective-C geliştirip çalıştıktan sonra Apple, geliştiricilere başka bir meydan okuma koymaya karar verdi. Bir kez daha iOS geliştiricilerinin yeni bir programlama dili öğrenmesi gerekecek: Swift . Swift, güvenli olmayan işaretçi yönetimini kaldırır ve hem Objective-C hem de C ile etkileşimi sürdürürken güçlü yeni özellikler sunar.
Swift 1.0 zaten istikrarlı ve güçlü bir geliştirme platformudur ve önümüzdeki yıllarda ilginç şekillerde gelişeceği kesindir. Açıkça iOS geliştirmenin geleceği olduğu için bu yeni dili keşfetmeye başlamak için mükemmel bir an.
Bu öğreticinin amacı, Objective-C geliştiricilerine yeni Swift dil özelliklerine hızlı bir genel bakış sunarak bir sonraki adımı atmanıza ve Swift'i günlük işlerinizde benimsemeye başlamanıza yardımcı olmaktır. Objective-C'yi açıklamak için çok fazla zaman harcamayacağım ve iOS geliştirmeye aşina olduğunuzu varsayacağım.
Swift ve Objective-C'yi denemek
Swift'i keşfetmeye başlamak için tek yapmanız gereken App Store'dan XCode'u indirmek ve deney yapmak için bir oyun alanı oluşturmak. Bu makalede bahsedilen tüm örnekler bu şekilde yapılmıştır.
Apple'ın Swift ana sayfası, Swift programlamayı öğrenmek için en iyi referanstır. Bunun paha biçilmez olduğunu göreceksiniz ve Swift geliştirme ile tamamen hızlanana kadar buraya sık sık geleceğinize inanıyorum.
Değişkenler ve Sabitler
Swift'de bir değişken bildirmek var
anahtar sözcüğü kullanılarak yapılır.
var x = 1 var s = "Hello"
İki değişken x
ve s
farklı türde olduğunu fark edeceksiniz. x
bir Tamsayıdır, s
ise bir Dizedir. Swift, güvenli bir tür dilidir ve atanan değerden değişken türleri çıkarır. Kodunuzu daha okunaklı hale getirmek istiyorsanız, isteğe bağlı olarak değişkenin türüne açıklama ekleyebilirsiniz:
var y: Int y = 2
Sabitler benzerdir, ancak onları var
yerine let
kullanarak bildirirsiniz. Bir sabitin değerinin derleme zamanında bilinmesi gerekmez, ancak ona tam olarak bir kez bir değer atamanız gerekir.
let c1 = 1 // Constant known at compile time var v = arc4random() let c2 = v // Constant known only at run time
Adlarından da anlaşılacağı gibi, bunlar değişmezdir, bu nedenle aşağıdaki kod bir derleme zamanı hatasına neden olur.
let c = 1 c = 3 // error
Diğer türler de sabit olarak bildirilebilir. Örneğin, aşağıdaki kod bir diziyi sabit olarak bildirir ve herhangi bir öğeyi değiştirmeye çalışırsanız Swift derleyicisi bir hata bildirir:
var arr2 = [4, 5, 6] arr2[0] = 8 print (arr2) // [8, 5, 6] let arr = [1, 2, 3] a[0] = 5 // error
Opsiyonel
Sabitler, bildirilirken başlatılmalı ve değişkenler kullanılmadan önce başlatılmalıdır. Peki Objective-C nil
eşdeğeri nerede? Swift, isteğe bağlı değerleri tanıtır. İsteğe bağlı değerler bir değere sahip olabilir veya nil
olabilir. Aşağıdaki koda bir göz atarsanız, x
Optional
bir 2014
değeri atandığını fark edeceksiniz. Bu, Swift derleyicisinin x
de nil
olabileceğinin farkında olduğu anlamına gelir.
var s = "2014" var x = s.toInt() print(x) // Optional(2014)
Bu kodda bir değişiklik yaparsanız ve "abc"
değerini bir Tamsayıya dönüştürülemeyen s
atarsanız, x
artık bir nil
olduğunu fark edeceksiniz.
var s = "abc" var x = s.toInt() print(x) // nil
toInt()
işlevinin dönüş türü Int?
, isteğe bağlı bir Int . x
üzerinde standart bir fonksiyon çağırmaya çalışalım:
var x = "2014".toInt() print(x.successor()) // error
x
isteğe bağlı olduğundan ve potansiyel olarak nil olabileceğinden , derleyici bir hata sinyali verir. Önce x
test etmeliyiz ve successor
işlevin nil
değerinde değil, gerçek bir sayı üzerinde çağrıldığından emin olmalıyız:
var x = "2014".toInt() if x != nil { print(x!.successor()) // 2015 }
Bir ünlem işareti (!) ekleyerek x
paketini açmamız gerektiğini unutmayın . x
bir değer içerdiğinden emin olduğumuzda ona erişebiliriz. Aksi takdirde çalışma zamanı hatası alırız. İsteğe bağlı olanı isteğe bağlı olmayan bir değişkene dönüştürerek Swift'in isteğe bağlı bağlama dediği şeyi de yapabiliriz.
let x = "123".toInt() if let y = x { print(y) }
if
ifadesindeki kod, yalnızca x
bir değeri varsa yürütülür ve onu y
atar. y
paketini açmamız gerekmediğine dikkat edin, x
nil
olmadığını bildiğimiz için type isteğe bağlı değildir.
İsteğe bağlı zincirleme gibi isteğe bağlı özellikler ve hoş özellikler hakkında daha fazla ayrıntı okumak için Apple'ın Swift eğitimine bakın
dize enterpolasyonu
Objective-C'de dizeleri biçimlendirme genellikle stringWithFormat:
yöntemiyle yapılır:
NSString *user = @"Gabriel"; int days = 3; NSString *s = [NSString stringWithFormat:@"posted by %@ (%d days ago)", user, days];
Swift'in aynısını yapmak için dize enterpolasyonu adı verilen bir özelliği vardır, ancak daha kompakt ve okunması daha kolaydır:
let user = "Gabriel" let days = 3 let s = "posted by \(user) \(days) ago"
Ayrıca şu ifadeleri de kullanabilirsiniz:
let width = 2 let height = 3 let s = "Area for square with sides \(width) and \(height) is \(width*height)"
Swift'in string enterpolasyonu ve diğer yeni özellikleri hakkında daha fazla bilgi edinmek için buraya gidin.
Fonksiyonlar
Swift'deki fonksiyon tanımı C'den farklıdır. Örnek bir fonksiyon tanımı aşağıdadır:
func someFunction(s:String, i: Int) -> Bool { ... // code }
Swift işlevleri birinci sınıf türlerdir . Bu, değişkenlere işlevler atayabileceğiniz, bunları diğer işlevlere parametre olarak iletebileceğiniz veya tür döndürmelerini sağlayabileceğiniz anlamına gelir:
func stringLength(s:String) -> Int { return countElements(s) } func stringValue(s:String) -> Int { if let x = s.toInt() { return x } return 0 } func doSomething(f:String -> Int, s:String) -> Int { return f(s).successor() } let f1 = stringLength let f2 = stringValue doSomething(f1, "123") // 4 doSomething(f2, "123") // 124
Yine Swift, f1
ve f2
( String
-> Int
) türlerini çıkarır, ancak bunları açıkça tanımlayabilirdik:
let f1:String -> Int = stringLength
İşlevler ayrıca diğer işlevleri de döndürebilir:
func compareGreaterThan(a: Int, b: Int) -> Bool { return a > b } func compareLessThan(a: Int, b: Int) -> Bool { return a < b } func comparator(greaterThan:Bool) -> (Int, Int) -> Bool { if greaterThan { return compareGreaterThan } else { return compareLessThan } } let f = comparator(true) println(f(5, 9))
Swift'deki işlevler için bir kılavuz burada bulunabilir.
numaralandırmalar
Swift'deki numaralandırmalar, Objective-C'dekinden çok daha güçlüdür. Swift yapıları olarak, yöntemlere sahip olabilirler ve değere göre iletilirler:
enum MobileDevice : String { case iPhone = "iPhone", Andro, WP8 = "Windows Phone8", BB = "BlackBerry" func name() -> String { return self.toRaw() } } let m = MobileDevice.Android print(m.name()) // "Android"
Objective-C'den farklı olarak Swift numaralandırmaları, tamsayıların yanı sıra her üye için değer olarak Dizeler, karakterler veya kayan noktalar atayabilir. Uygun toRaw()
yöntemi, her üyeye atanan değeri döndürür.
Numaralandırmalar ayrıca parametrelenebilir:
enum Location { case Address(street:String, city:String) case LatLon(lat:Float, lon:Float) func description() -> String { switch self { case let .Address(street, city): return street + ", " + city case let .LatLon(lat, lon): return "(\(lat), \(lon))" } } } let loc1 = Location.Address(street: "2070 Fell St", city: "San Francisco") let loc2 = Location.LatLon(lat: 23.117, lon: 45.899) print(loc1.description()) // "2070 Fell St, San Francisco" print(loc2.description()) // "(23.117, 45.988)"
Numaralandırmalar hakkında daha fazla bilgiyi burada bulabilirsiniz.

demetler
Tuples, birden çok değeri tek bir bileşik değerde gruplandırır. Bir tanımlama grubu içindeki değerler herhangi bir türden olabilir ve birbirleriyle aynı türden olmaları gerekmez.
let person = ("Gabriel", "Kirkpatrick") print(person.0) // Gabriel
Ayrı ayrı demet öğelerini de adlandırabilirsiniz:
let person = (first: "Gabriel", last: "Kirkpatrick") print(person.first)
Tuple'lar, birden fazla değer döndürmesi gereken işlevler için dönüş türleri olarak son derece uygundur:
func intDivision(a: Int, b: Int) -> (quotient: Int, remainder: Int) { return (a/b, a%b) } print(intDivision(11, 3)) // (3, 2) let result = intDivision(15, 4) print(result.remainder) // 3
Objective-C'den farklı olarak Swift, bir switch ifadesinde kalıp eşleştirmeyi destekler:
let complex = (2.0, 1.1) // real and imaginary parts switch complex { case (0, 0): println("Number is zero") case (_, 0): println("Number is real") default: println("Number is imaginary") }
İkinci durumda, sayının gerçek kısmıyla ilgilenmiyoruz, bu yüzden herhangi bir şeyi eşleştirmek için bir _
kullanıyoruz. Her durumda ek koşulları da kontrol edebilirsiniz. Bunun için kalıp değerlerini sabitlere bağlamamız gerekiyor:
let complex = (2.0, 1.1) switch complex { case (0, 0): println("Number is zero") case (let a, 0) where a > 0: println("Number is real and positive") case (let a, 0) where a < 0: println("Number is real and negative") case (0, let b) where b != 0: println("Number has only imaginary part") case let (a, b): println("Number is imaginary with distance \(a*a + b*b)") }
Yalnızca karşılaştırmada veya case ifadesinde kullanacağımız değerleri nasıl bağlamamız gerektiğine dikkat edin.
Tuple'lar hakkında daha fazla okumak için buraya gidin.
Sınıflar ve Yapılar
Objective-C'den farklı olarak Swift, özel sınıflar ve yapılar için ayrı arayüz ve uygulama dosyaları oluşturmanızı gerektirmez. Swift'i öğrendikçe, tek bir dosyada bir sınıf veya yapı tanımlamayı öğreneceksiniz ve bu sınıf veya yapının harici arayüzü otomatik olarak diğer kodların kullanması için hazır hale getirilecek.
Sınıfları Tanımlama
Sınıf tanımları çok basittir:
class Bottle { var volume: Int = 1000 func description() -> String { return "This bottle has \(volume) ml" } } let b = Bottle() print(b.description())
Gördüğünüz gibi, beyan ve uygulama aynı dosyada . Swift artık başlık ve uygulama dosyalarını kullanmıyor. Örneğimize bir etiket ekleyelim:
class Bottle { var volume: Int = 1000 var label:String func description() -> String { return "This bottle of \(label) has \(volume) ml" } }
Derleyici, etiket isteğe bağlı olmayan bir değişken olduğundan şikayet eder ve bir Bottle başlatıldığında bir değeri tutmaz. Bir başlatıcı eklememiz gerekiyor:
class Bottle { var volume: Int = 1000 var label:String init(label:String) { self.label = label } func description() -> String { return "This bottle of \(label) has \(volume) ml" } }
Veya, başlatılmayacak bir özellik için Optional
türü kullanabiliriz. Aşağıdaki örnekte, volume
bir Optional Integer
yaptık:
class Bottle { var volume: Int? var label:String init(label:String) { self.label = label } func description() -> String { if self.volume != nil { return "This bottle of \(label) has \(volume!) ml" } else { return "A bootle of \(label)" } } }
Yapılar
Swift dilinde de structs
vardır, ancak bunlar Objective-C'den çok daha esnektir. Aşağıdaki kod öğreticisi bir struct
tanımlar:
struct Seat { var row: Int var letter:String init (row: Int, letter:String) { self.row = row self.letter = letter } func description() -> String { return "\(row)-\(letter)" } }
Swift'deki sınıflar gibi, yapılar da yöntemlere, özelliklere, başlatıcılara sahip olabilir ve protokollere uygun olabilir. Sınıflar ve yapılar arasındaki temel fark, sınıfların referansa göre, yapıların ise değere göre iletilmesidir .
Bu örnek, referans yoluyla sınıfları geçmeyi gösterir:
let b = Bottle() print(b.description()) // "b" bottle has 1000 ml var b2 = b b.volume = 750 print(b2.description()) // "b" and "b2" bottles have 750 ml
struct
ile benzer bir durumu denersek, değişkenlerin değere göre iletildiğini fark edeceksiniz:
var s1 = Seat(row: 14, letter:"A") var s2 = s1 s1.letter = "B" print(s1.description()) // 14-B print(s2.description()) // 14-A
Ne zaman struct
ve ne zaman class
kullanmalıyız? Objective-C ve C'de olduğu gibi, birkaç değeri gruplamanız gerektiğinde yapıları kullanın ve referans vermek yerine kopyalanmalarını bekleyin. Örneğin, karmaşık sayılar, 2B veya 3B noktalar veya RGB renkleri.
Bir sınıfın bir örneği, geleneksel olarak bir nesne olarak bilinir. Bununla birlikte, Swift sınıfları ve yapıları, işlevsellik açısından diğer dillere göre çok daha yakındır ve bir sınıf ya da yapı türünün örneklerine pek çok işlevsellik uygulanabilir. Bu nedenle, Swift başvurusunda kullanılan daha genel terim, bu ikisinden herhangi biri için geçerli olan instance
.
Swift sınıflarının ve yapılarının temellerini buradan öğrenin.
Özellikleri
Daha önce gördüğümüz gibi, Swift'deki özellikler bir sınıf veya yapı tanımı içinde var
anahtar sözcüğü ile bildirilir. Sabitleri bir let
deyimi ile de bildirebiliriz.
struct FixedPointNumber { var digits: Int let decimals: Int } var n = FixedPointNumber(digits: 12345, decimals: 2) n.digits = 4567 // ok n.decimals = 3 // error, decimals is a constant
Ayrıca, weak
anahtar sözcüğüyle önek eklemediğiniz sürece, sınıf özelliklerine güçlü bir şekilde başvurulduğunu unutmayın. Ancak isteğe bağlı olmayan özelliklerin zayıf olduğu bazı incelikler vardır, bu nedenle Apple'ın Swift kılavuzundaki otomatik referans sayma bölümünü okuyun.
Hesaplanan Özellikler
Hesaplanan özellikler aslında bir değer saklamaz. Bunun yerine, diğer özellikleri ve değerleri dolaylı olarak almak ve ayarlamak için bir alıcı ve isteğe bağlı bir ayarlayıcı sağlarlar.
Aşağıdaki kod, hesaplanan değer sign
bir örneğini sağlar:
enum Sign { case Positive case Negative } struct SomeNumber { var number:Int var sign:Sign { get { if number < 0 { return Sign.Negative } else { return Sign.Positive } } set (newSign) { if (newSign == Sign.Negative) { self.number = -abs(self.number) } else { self.number = abs(self.number) } } } }
Yalnızca bir alıcı uygulayarak salt okunur özellikleri de tanımlayabiliriz:
struct SomeNumber { var number:Int var isEven:Bool { get { return number % 2 == 0 } } }
Objective-C'de, özellikler genellikle derleyici tarafından açıkça veya otomatik olarak oluşturulan bir örnek değişken tarafından desteklenir. Öte yandan Swift'de, bir özelliğin karşılık gelen bir örnek değişkeni yoktur . Diğer bir deyişle, bir mülkün destek deposuna doğrudan erişilemez. Bunun Objective-C'de olduğunu varsayalım.
// .h @interface OnlyInitialString : NSObject @property(strong) NSString *string; @end // .m @implementation OnlyInitialString - (void)setString:(NSString *newString) { if (newString.length > 0) { _string = [newString substringToIndex:1]; } else { _string = @""; } } @end
Swift'de hesaplanan özelliklerin bir destek deposu olmadığından, şöyle bir şey yapmamız gerekiyor:
class OnlyInitialString { var initial:String = "" var string:String { set (newString) { if countElements(newString) > 0 { self.initial = newString.substringToIndex(advance(newString.startIndex, 1)) } else { self.initial = "" } } get { return self.initial } } }
Özellikler burada daha ayrıntılı olarak açıklanmıştır
Devam edecek
Generics, Objective-C kitaplıkları ile etkileşim, kapatmalar, isteğe bağlı zincirleme ve operatör aşırı yüklemesi gibi Swift'de öğrenilecek çok daha önemli yeni şeyler var. Tek bir öğretici, yeni bir dili tam olarak tanımlayamaz, ancak Swift programlamayı öğrenmek hakkında çok daha fazlasının yazılacağından şüphem yok. Ancak, bu hızlı okumanın , Swift dilinin ayrıntılarını öğrenmeyi ve zaman bulmayı başaramayan birçok Objective-C geliştiricisinin doğru yola girmesine ve Swift kuşunun onları yeni zirvelere taşımasına yardımcı olacağına inanıyorum.