2014-09-16 9 views
6

potrei un'istanza di classe da stringa a ObjC.For esempio, ho definito nuova classe DBCell attraverso sottoclasse UITableViewCell, e un'istanza di classe dal nome con questi codici:Come istanziare la classe e init dalla stringa in Swift?

DBCell *cell=[tableView dequeueReusableCellWithIdentifier:cellClassname]; 
    if (cell==nil) { 
     Class cellClass=NSClassFromString(cellClassname); 
     cell=[cellClass alloc]; 
     cell=[cell initWithStyle:cellStyle reuseIdentifier:cellClassname]; 
    } 

Ora ho bisogno di migrare i codici a Swift, I hanno ridefinito classe DBCell a Swift:

class DBCell: UITableViewCell { 
    var label:String? 
    var key:String? 
    var managedObject:NSManagedObject? 
    var delegate:AnyObject? 
    convenience override init(style: UITableViewCellStyle, reuseIdentifier: String!) { 
     self.init(style: style, reuseIdentifier: reuseIdentifier) 
     self.textLabel.font=UIFont.preferredFontForTextStyle(UIFontTextStyleCaption1) 
     self.backgroundColor=UIColor.blackColor() 
     self.textLabel.backgroundColor=UIColor.blackColor() 
    } 
    } 

Ma come posso istanziare classe e richiamare la funzione init appropriati?

+0

Ritengo che il problema sia causato da una cattiva architettura, principalmente dalla mancanza di un polimorfismo correttamente utilizzato. Potresti mostrare più del tuo codice originale obj-c? Qual è la differenza tra celle diverse? – Sulthan

+0

@Sulthan Questo è un modello di cacao piuttosto comune. Cosa intendi con "polimorfismo correttamente utilizzato" in questo caso? Il punto è che i nomi delle celle sono memorizzati nello storyboard, che è abbastanza comodo e utile. La domanda è come farlo mantenendo la sicurezza del tipo Swift (ed è una domanda ragionevole). –

risposta

15

Swift è più tipizzato in modo statico, il che lo rende molto più sicuro in fase di esecuzione. Ad esempio, se una delle stringhe è sbagliata, ti troverai in crash (o nel migliore dei casi non fare nulla, il che può essere peggio di un arresto anomalo) e il compilatore non può prenderlo per te.

OK, ma come si gestisce questo schema? Il modo migliore, IMO, in Swift è di essere esplicito e creare una mappatura.

let cellMapping = [ 
    "DBCell": DBCell.self, 
] 

if let cellClass = cellMapping[cellClassName] { 
    let cell = cellClass(style: cellStyle, reuseIdentifier: cellClassName) 
    // use cell 
} 

Ora, quando si refactoring e modifica il nome di DBCell, ma manca la stringa nella Storyboard, tutto ciò sarà solo continuare a lavorare come previsto, invece di schiantarsi o tranquillamente in mancanza di come sarebbe in objC.

Anche Swift è molto intelligente su questi mapping. Il tipo di cellMapping sopra è [String: DBCell.Type], quindi se avessi uno speciale init per DBCell, sarebbe disponibile. Ma se il vostro dizionario sembrava:

let cellMapping = [ 
    "DBCell": DBCell.self, 
    "OtherCell": UITableViewCell.self 
] 

quindi il tipo è [String: UITableViewCell.Type]. Swift calcola automaticamente la classe più specifica che copre tutti i valori. Se hai aggiunto un tipo in questo elenco che non ha un metodo che usi effettivamente, Swift può prenderlo al momento della compilazione. E se hai fatto un errore e ha aggiunto qualcosa che non è nemmeno una cella di vista tabella:

let cellMapping = [ 
    "DBCell": DBCell.self, 
    "OtherCell": UITableViewCell.self, 
    "BadCell": UICollectionViewCell.self 
] 

poi Swift vi darà un tempo di compilazione di avvertimento che hai creato un AnyObject. È davvero bello scrivere un codice sicuro ma flessibile, tutto per il costo di un dizionario.

+0

Grazie, ha funzionato! – user1190178

+0

C'è un modo per creare una mappatura di celle che faccia funzionare questo con tipi diversi? –

+0

Non capisco la domanda. Dovresti fare una nuova domanda SO con i dettagli del tuo problema specifico. –

Problemi correlati