İnit coder aDecoder tam olarak nedir?


122

Çevrimiçi bir kurstan iOS geliştirmeyi öğreniyorum ve her özel görünüm oluşturduğumda (özel tablo görünümü hücresi, koleksiyon görünümü hücresi vb.) Eğitmen her zaman şu başlatıcıyı uygular:

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

Neden her zaman tam olarak bunu aramak zorundayım? Bu ne işe yarıyor? Girişin içine özellikler koyabilir miyim?


5
Bu cevap size stackoverflow.com/questions/24036393/… yardımcı olacaktır. Teşekkürler
Seungyoun Yi

2
Uygulayan bir nesneyi alt NSCodingsınıflarsanız, uygulayan sınıflar için gerekli olduğundan, bu başlatıcıyı uygulamanız gerekir NSCoding. En azından süper sınıf başlatma yöntemini çağırmalısınız. Eğer NSCodersenin sınıf için kodlanmış özelliklerini içeren o zaman o kurtarmak için bu yöntemi kullanabilirsiniz
Paulw11

1
Ayrıca, Apple'ın resmi Swift kitabındaki nesne ilkleştirme hakkındaki bölümü okumanızı tavsiye ederim.
Nicolas Miari

Yanıtlar:


121

Bu yanıta ters yönden başlayacağım: Ya görünümünüzün durumunu diske kaydetmek istiyorsanız? Bu, serileştirme olarak bilinir . Bunun tersi seriyi kaldırmadır - nesnenin durumunu diskten geri yüklemek.

NSCodingProtokol serileştirip Deserialize nesneler için iki yöntem tanımlar:

encodeWithCoder(_ aCoder: NSCoder) {
    // Serialize your object here
}

init(coder aDecoder: NSCoder) {
    // Deserialize your object here
}

Öyleyse neden özel sınıfınızda buna ihtiyaç var? Cevap, Arayüz Oluşturucu. Bir nesneyi bir film şeridine sürükleyip yapılandırdığınızda, Arabirim Oluşturucu o nesnenin durumunu diskte serileştirir, ardından film şeridi ekranda göründüğünde serisini kaldırır. Interface Builder'a bunları nasıl yapacağını söylemeniz gerekiyor. En azından, alt sınıfınıza herhangi bir yeni özellik eklemezseniz, süper sınıfa sizin için paketleme ve açma işlemlerini yapmasını isteyebilirsiniz, dolayısıylasuper.init(coder: aDecoder) çağrı. Alt sınıfınız daha karmaşıksa, alt sınıf için kendi serileştirme ve serileştirme kodunuzu eklemeniz gerekir.

Bu, nesneyi çalışma zamanında yapmak için kodu gizli bir dosyaya yazmak olan Visual Studio'nun yaklaşımının tersidir.


Neden her şeyi uyanıkFromNib'in içine koyup kullanmayı unutmuyorsunuz init(coder aCoder : NSCoder)?
Tatlım

@Honey - tek kelimeyle, "bazen bunu yapamazsınız". Genelde yapabilirsin ama her zaman değil.
Şişko

@ Fatie, bunu çok karmaşık veya bilinmesi gereksiz yapmamanın detayları mı? Eğer açıklamayı düşünmez misin?
Honey

9
@Honey, nesnenizi Interface Builder'da yapılandırmak istiyorsanız awakeFromNibçalışmayacaktır. çalışma zamanındaawakeFromNib çağrılır . Interface Builder'da yaptığınız her şey tasarım sırasında yapılır . Eğer yaptıklarınızı taşımak için tasarım zamanında üzere çalışma zamanında edilir (tasarruf) ve (yükleme)encodeWithCoderinit(coder:)
Farklı Kanunu

3
@Honey, özel sınıfınızı yapılandırmak için Arayüz Oluşturucu kullanmıyorsanız (yani, kodla programlı olarak yapın), o zaman bunu yapabilirsiniz awakeFromNibveyainitWIthFrame
Farklı Kod

28

Bu başlatıcıyı uygulama gereksinimi iki şeyin sonucudur:

  1. Liskov ikame prensibi . S, T'nin bir alt sınıfı ise (örneğin MyViewController, bir alt sınıfı ise ViewController), MyViewControllerT nesnelerinin (örnekleri ViewController) beklendiği yerde S nesnelerinin (örnekleri ) ikame edilebilmesi gerekir .

  2. Başlatıcılar, alt sınıfta açıkça tanımlanmış herhangi bir başlatıcı varsa, Swift'de miras alınmaz. Bir başlatıcı açıkça sağlanmışsa, diğerlerinin tümü açıkça sağlanmalıdır (bu, daha sonra sadece çağrılabilir super.init(...)). Gerekçe için bu soruya bakın . Java'da, ancak yine de geçerlidir.

1. maddeye göre, orijinalin ViewControlleryapabileceği her şeyi , MyViewControlleralt sınıfın yapabilmesi gerekir. Böyle bir şey, bir veriden başlatılabilmektir NSCoder. 2. MyViewControllermaddeye göre, alt sınıfınız bu yeteneği otomatik olarak devralmaz. Bu nedenle, bu gereksinimi karşılayan başlatıcıyı manuel olarak sağlamalısınız. Bu durumda, genellikle yapacağı şeyi yapması için süper sınıfa yetki vermeniz yeterlidir.


1
Yapıcıların miras alınmaması mükemmel bir anlam ifade ediyor: Temel sınıfın (miras alınan) başlatıcısını kullanarak türetilmiş sınıfın bir örneğini başlatırsanız, türetilmiş sınıf tarafından yeni tanımlanan ("eklenen") miras alınmayan özellikler asla başlatılabilir.
Nicolas Miari

3
Aslında, kendi alt sınıfınızda kendi başlatıcı uygulamalarınızdan hiçbirini sağlamadığınız için, başlatıcılar Swift'de miras alınır. Yeni tanımlanmış miras alınmayan özelliklerinizin varsayılan değerleri varsa, alt sınıfınızda herhangi bir başlatıcı yazmamaktan kurtulabilir ve üst sınıfınızın tüm başlatıcılarını devralabilirsiniz. Buraya
TheBaj
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.