2015-04-18 12 views
6

Sto provando a creare una sottoclasse UITableViewController generica in Swift che può ospitare un numero qualsiasi di diversi tipi di celle di visualizzazione tabella senza avere una conoscenza interna di nessuno di essi.Rendere la classe swift conforme al protocollo - a livello statico/classe

Per fare ciò, sto cercando di utilizzare i protocolli per i miei modelli e per le celle di visualizzazione tabella. Il protocollo per i modelli restituirà quale classe di celle dovrei raggiungere e il protocollo per le celle restituirà risposte a domande come l'altezza della cella per un dato modello.

Ma sto riscontrando un problema nel far funzionare i protocolli, perché con il secondo protocollo voglio passare alla classe della cella piuttosto che alla sua istanza.

Il protocollo per i modelli è la seguente:

protocol JBSTableItemDelegate 
{ 
    func tableCellDelegate() -> JBSTableViewCellInterface 
} 

Il protocollo per le cellule è la seguente:

protocol JBSTableViewCellInterface: class 
{ 
    static func registerNibsWithTableView(tableView: UITableView) 

    static func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath?, tableItem: JBSTableItemDelegate) -> CGFloat 

    static func tableView(tableView: UITableView, dequeueReusableCellWithIndexPath indexPath: NSIndexPath, tableItem: JBSTableItemDelegate, delegate: AnyObject) -> JBSTableViewCell 
} 

Avviso l'utilizzo della parola chiave "statica". Questi metodi sono metodi di classe nelle sottoclassi UITableViewCell e l'aggiunta di statico sembra essere ciò che devo fare per verificare che tali classi siano conformi, o almeno così comprendo.

Quando uso il primo protocollo il codice assomiglia così, e si compila:

let tableViewCellInterface = tableItem!.tableViewCellInterface() 

E 'di chiamare questo metodo (come un esempio):

func tableViewCellInterface() -> JBSTableViewCellInterface 
{ 
    return JBSLiteratureTableViewCell.self as! JBSTableViewCellInterface 
} 

Questo restituisce la classe del cella, ad esempio "JBSLiteratureTableViewCell.self"

Quando utilizzo il secondo protocollo, il codice è simile al seguente e non viene compilato:

returnFloat = tableViewCellInterface.tableView(tableView, heightForRowAtIndexPath: indexPath, tableItem: tableItem!) 

Non riesce a compilare a causa della parola chiave static in precedenza, e l'errore del compilatore che ottengo è:

'JBSTableViewCellInterface' non ha un membro denominato 'tableView'

Se tolgo le parole chiave statiche dal protocollo funcs, compila, ma le sottoclassi UITableViewCell si lamentano dicendo:

'JBSLiteratureTableViewCell' non è conforme al protocollo 'JBSTableViewCellInterface'

Questo è perché stanno ora cercando di rendere sicuri esistono metodi di istanza, che non è dove questi sono.

Come faccio a rendere una classe rapida conforme a un protocollo a livello di classe, quindi può essere il mio delegato piuttosto che qualche istanza di una classe? Sono sicuro che potrei aggirare questo creando classi di helper del protocollo JBSTableViewCellInterface che sono singleton e lasciare che facciano il lavoro, ma preferirei costruirlo direttamente nelle sottoclassi di UITableViewCell nei loro metodi di classe.

+0

Davvero? Avete un link? –

risposta

5

aggiornato per Swift versione 2.0 e superiori

Come per la risposta di Gregzo, Swift 2.0+ permette metodi da dichiarare secondo quanto statico nella definizione del protocollo. Questi devono essere soddisfatti con metodi statici/di classe negli oggetti che implementano il protocollo.

Non è possibile soddisfare una definizione di protocollo per un metodo di istanza con un metodo statico o viceversa, il che rende questa risposta incompleta per la domanda precedente.

Se volete provare questo basta usare la parola "statica" nella definizione di protocollo per i metodi si implementare i metodi statici o di classe in oggetti conformi:

protocol InstanceVsStatic { 
    func someInstanceFunc() 
    static func someStaticFunc() 
} 

enum MyConformingEnum: InstanceVsStatic { 
    case someCase 

    static func someStaticFunc() { 
      // code 
    } 
    func someInstanceFunc() { 
     // code 
    } 
} 

class MyConformingClass: InstanceVsStatic { 
    class func someStaticFunc() { 
      // code 
    } 
    func someInstanceFunc() { 
     // code 
    } 
} 

struct MyConformingStruct: InstanceVsStatic { 
    static func someStaticFunc() { 
      // code 
    } 
    func someInstanceFunc() { 
     // code 
    } 
} 

Si può avere un metodo di istanza chiama un metodo static/class:

Ciò consente di eseguire codice statico quando è necessario conformarsi a un protocollo che richiede un metodo di istanza.

struct MyConformingStruct: InstanceVsStatic { 
    static func doStuffStatically(){ 
     // code 
    } 

    static func someStaticFunc() { 
      // code 
    } 

    func someInstanceFunc() { 
     MyConformingStruct.doStuffStatically() 
    } 
} 

Swift 1.2

Altro che indirettamente come sopra, non c'è modo di usare metodi statici (di classe) a conformarsi a un protocollo in puro rapida versione 1.2 e di seguito. Si tratta di una caratteristica bug/non implementata: https://openradar.appspot.com/20119848

+0

Ti chiedi se ci sarà una funzionalità in futuro? –

2

Se un Funz protocollo è statico, il realizzatore deve implementare come un metodo statico, e se non lo è, come metodo di istanza:

protocol MixedProtocol 
{ 
    static func staticFoo() 
    func instanceBar() 
} 

class ExampleClass : MixedProtocol 
{ 
    // implementing static func as class func is fine. 
    // class funcs are overridable, not static ones 
    class func staticFoo() 
    { 
     println("I'm a class func") 
    } 

    func instanceBar() 
    { 
     println("I'm an instance func") 
    } 
} 

Non c'è modo rettilineo intorno ad esso: conforme ad un protocollo significa proprio questo, e 'static' è una caratteristica fondamentale di una dichiarazione di membro del protocollo che gli implementatori devono rispettare.

Problemi correlati