2014-11-28 25 views
6

tl; dr Nesnenin amaçlanan türünü korurken, bir nesneyi uygun bir iletişim kuralı başlatıcısı yöntemini kullanarak genel olarak örneklendirebilir misiniz? Şimdi denediğim şey derleyiciyi parçalamak. Ben yazıyorum Kütüphanede Swift Genel Nesne/JSON Serileştirme


, ben Swift'in sınırlı introspection özelliklerini kullanarak jenerik Serileştirme/deserializing nesnelerin hedefe ulaşmak için çalışıyorum.

Yansımayı kullanarak bir değişkenin değerini ayarlayan genel bir işlevin kodu. şeylerden

func model__setValue<T where T: NSObject, T: Serializable>(value: AnyObject, forSerializationKey key: String, model m: T) { 
    let varNames = object__getVarNames(mirror: reflect(m)) // Gets a list of this object's variable names 
    if let i = find(m.serializationKeys, key) { 
     if value is [String : AnyObject] { 
      // This allows us to have nested dictionary representations 
      // of Serializable constructs and have them init properly 
      let t1 = reflect(m)[i].1.valueType as NSObject.Type 
      if t1 is Serializable.Type { 
       let t2 = t1 as Serializable.Type 
       let finalObj = t2(dictionary: value as [String : AnyObject]) // Segmentation fault: 11 
       m.setValue(finalObj, forKey: varNames[i]) 
      } 
     } else { 
      m.setValue(value, forKey: varNames[i]) 
     } 
    } 
} 

Çift açıklamaya:

  1. Serializable init (sözlük) dahil yöntemleri tanımlayan bir protokoldür o bir sözlük bulursa iç içe yapılar için uzlaştırmak için çalışır. Seri haline getirilmek istenen nesneler tarafından benimsenir.
  2. Serializable ayrıca "serileştirme tuşları" nın bir hesaplanmış özelliğini veya nesnenin değişkenleri için sözlük anahtarları olarak kullanılan dizelerin bir listesini belirtir ve serileştirme anahtarlarına değişken adlarının bire bir eşleştirmesi olmalıdır. Neden böyle? Bazen API, artık gerçekten anlam ifade etmeyen geri dönüş tuşlarını çağırıyor (şema çürüğü mü?), Ya da bir değişkeni farklı şekilde adlandırmak istiyorum, çünkü çok fazla alttan zevk almıyorum.
  3. Modelin her ikisi de NSObject olmalıdır ve Serializable ile uyumludur. Niye ya? Bunun gibi jeneriklere ulaşmak için, bir nesnenin alanlarına tanımlayıcılarını önceden bilmeden yazabilme yeteneğine ihtiyacım vardı. Swift'in bunu yerel olarak yapmanın bir yolu yok, bu yüzden NSObject'i alt sınıflara ayırmak iyi bir uzlaşmadır. Neden bu özelliklerle bir kök nesnesi olmasın?

Buradaki amacım JSON gösterimlerinden (yuvalanmış nesnelerle bile farklı tuşlar ve değişken adlarda bile) gelen nesnelerin aptal, kolay, düşük genel yapısıdır. Bu yüzden bir nesne verin, buradaki anahtarların listesini yapın ve protokolün init nesnesinin değişkenleri üzerinde yineleyen ve her seferinde çağrı yapan başka bir genel yapıcı işlevini çağırmasını sağlayın. Bam. Bu kadar. Artık tüm (JSON) API'lardan tüm şeyleri ayrıştırabilir ve çok az ya da hiç ayrıştırma mantığı yazabilirsiniz. Aynı şekilde bir seri hale getiriciye de başvurmak istedim, öyle ki toDictionary sadece bir genel yöntem çağrısı gerektiriyor.

Bu işlevde, bir nesnenin değerini yansıtma kullanarak dinamik olarak ayarlıyoruz. Öncelikle, bu nesneye ayarlamak için geçerli bir anahtar olduğundan emin olun. Ardından, ayarlamak istediğimiz değerin bir sözlük olup olmadığını belirleriz. Öyleyse, aslında Serializable uyumlu bir tip olup olmadığını görmek için hedef nesnesinin türünü almak istiyorum. Bu alan varsa, bu sözlüğü tekrarlı olarak oluşturmak için kullanabiliriz (bu kısaca açıklandığı gibi çalışmaz). Değilse veya değer bir sözlük değilse, yalnızca Cocoa'nın setValue: forKey: yöntemini kullanın.

Ne yazık ki, yuvalanmış nesnenin oldukça düzgün çalışmasını sağlayamıyorum ve yapmaya çalıştığım şeyin tamamen imkansız mı yoksa sadece yanlış mı yapıyorsam çözemedim. Ayrıca, Xcode'un üzerinde bir hata olmamasına rağmen let finalObj hattımın geçerli olmadığını düşünüyorum. Düşünce sürecim sadece Serializable'un init yapıcısını çağırıp benim yoluma devam etmektir. Ben bu sorunun Swift'in statik olarak yazılan doğası olduğunu ve derleyicinin aslında init'in ne tür bir son türünü döndüreceğini bilmediğini düşünüyorum (ancak Xcode'un bu satırdaki t2 anahtar sözcüklerle aynı renkte olmasına rağmen).Eğer t1 NSObjectda 'un Serializable ile uyumlu olduğunu söylemenin bir yolu olup olmadığından emin değilim. Ben şimdi t2 ile girişimi düşünüyorum ve döküm tipi bilgi kaybediyor ve böylece seg hataya neden, yine de Xcode aslında ben inşa etmek kadar gitmek için bu konuda şikayet etmez.

Bu iç içe geçmiş Serializable bir şeyi uzlaştırmanın birkaç yolunu denedim ve bir çözüm bulamadılar. Herhangi biri yardımcı olabilir mi?

+0

Yapmaya çalıştığınız şeyi anlıyorum, ancak "Seri hale getirilebilir" neye benziyor? –

+0

'Serializable' [bu] 'a benziyor (https://github.com/ArtisOracle/libSwiftCal/blob/master/libSwiftCal/Serializable.swift) ve genel işlevler [burada] (https://github.com/ArtisOracle/ libSwiftCal/blob/master/libSwiftCal/CalendarObject.swift) gerçekten çalışmasını sağlayın. Bu kodda, yukarıda açıklandığı gibi,% 100 jenerik olarak çalışmadığı için etrafta bir çalışma yaptım. –

+0

SwiftyJSON'a bir göz atın. – adamek

cevap