2016-03-16 17 views
6

Ho diverse classi veloci che sembrano simili come il seguenteCome estrarre i valori digitati facoltativi da Mirror child in Swift?

public class Book { 
    var title: String? 
    var date: NSDate? 
} 

come ci sono diverse classi diverse in cui ho bisogno di accedere alle proprietà, sto usando riflessione a correre attraverso le proprietà della classe:

let myBook = Book() 
myBook.title = "Hello" 
myBook.date = NSDate() 

let mirror = Mirror(reflecting: myBook) 
var propsArr = [(key: String?, value: Any)]() 
let mirrorChildrenCollection = AnyRandomAccessCollection(mirror.children)! 
if mirrorChildrenCollection.count > 0 { 
    propsArr += mirrorChildrenCollection 
} 

//iterate through properties 
for case let (label?, value) in propsArr { 
    print (label, value) 

    if let val = value as? NSDate { 
    var extractedDate = val 
    print(extractedDate) 
    } 
    else if let val = value as? String { 
    var extractedTitle = val 
    print (extractedTitle) 
    } 
} 

Ma ho un problema che gli oggetti figlio non vengono estratti in quanto sono di tipo Qualsiasi e le classi internamente opzionali e quindi non rientrano nei miei casi. Se cambio titolo da String? a String, funzionano, ma ho bisogno di usare i tipi opzionali.

Cosa posso modificare nell'implementazione precedente per lasciare il tipo di dati come String? e data? e ancora estrai i valori dallo specchio?

risposta

4

Sembra che questo non sia possibile in Swift 2.x.

Dal momento che le proprietà sono optionals, si dovrà lanciare a NSDate? e String? rispettivamente, in questo modo:

if let val = value as? NSDate? { 
    // val is Optional<NSDate> 
} 

Purtroppo, il compilatore non permette questo (io non sono sicuro perché): // error: cannot downcast from 'protocol<>' to a more optional type 'NSDate?'.

This answer da bubuxu fornisce una soluzione intelligente che potrebbe funzionare se si dispone di un Mirror per ogni proprietà. La proprietà displayStyle del mirror indica se è facoltativa e quindi è possibile estrarre manualmente il valore spostato. Quindi questo dovrebbe funzionare:

let child = Mirror(reflecting: myBook.date) 
child.displayStyle 
if child.displayStyle == .Optional { 
    if child.children.count == 0 { 
     // .None 
    } else { 
     // .Some 
     let (_, some) = child.children.first! 
     if let val = some as? NSDate { 
      print(val) 
     } 
    } 
} 

Ma questo dipende da avere un Mirror per ogni proprietà, e sembra non si può attraversare i bambini 's un Mirror per recuperare Mirror s per loro.