2016-06-22 54 views
12

Poiché le proprietà statiche memorizzate non sono (ancora) supportate per i tipi generici in swift, mi chiedo quale sia una buona alternativa.Qual è una buona alternativa per le proprietà statiche memorizzate di tipi generici in swift?

Il mio caso specifico è che voglio creare un ORM in rapido. Ho un protocollo Entity che ha un tipo associato per la chiave primaria, dal momento che alcune entità avranno un numero intero come loro id e alcune avranno una stringa ecc. In questo modo il protocollo Entity è generico.

Ora ho anche un tipo EntityCollection<T: Entity>, che gestisce le raccolte di entità e come puoi vedere è anche generico. L'obiettivo di EntityCollection è che consente di utilizzare raccolte di entità come se fossero normali array senza dover essere consapevoli del fatto che dietro di essi c'è un database. EntityCollection si occuperà di query e memorizzazione nella cache e di essere il più ottimizzato possibile.

Desidero utilizzare le proprietà statiche su EntityCollection per archiviare tutte le entità che sono già state recuperate dal database. In questo modo se due istanze separate di EntityCollection vogliono recuperare la stessa entità dal database, il database verrà interrogato solo una volta.

Ragazzi, avete idea di come potrei ottenerlo?

risposta

0

Tutto ciò che posso inventare è separare la nozione di origine (da cui proviene la raccolta) e quindi la raccolta stessa. E poi la fonte responsabile della memorizzazione nella cache. A quel punto la sorgente può essere effettivamente un'istanza, quindi può conservare qualunque cache voglia/necessità e la tua EntityCollection è solo responsabile del mantenimento di un protocollo CollectionType e/o SequenceType attorno all'origine.

Qualcosa di simile:

protocol Entity { 
    associatedtype IdType : Comparable 
    var id : IdType { get } 
} 

protocol Source { 
    associatedtype EntityType : Entity 

    func first() -> [EntityType]? 
    func next(_: EntityType) -> [EntityType]? 
} 

class WebEntityGenerator <EntityType:Entity, SourceType:Source where EntityType == SourceType.EntityType> : GeneratorType { ... } 

classe WebEntityCollection: SequenceType {...}

funzionerebbe se si dispone di un interfaccia dati web tipica di paging. Quindi potresti fare qualcosa sulla falsariga di:

class WebQuerySource<EntityType:Entity> : Source { 
    var cache : [EntityType] 

    ... 

    func query(query:String) -> WebEntityCollection { 
     ... 
    } 
} 

let source = WebQuerySource<MyEntityType>(some base url) 

for result in source.query(some query argument) { 
} 

source.query(some query argument) 
     .map { ... } 
     .filter { ... } 
0

Qualcosa di simile?

protocol Entity { 

} 

class EntityCollection { 
    static var cachedResults = [Entity]() 

    func findById(id: Int) -> Entity? { 
     // Search cache for entity with id from table 

     // Return result if exists else... 

     // Query database 

     // If entry exists in the database append it to the cache and return it else... 

     // Return nil 
    } 
} 
+3

che non funziona per me da quando sto lavorando con i tipi generici e quei tipi non permettere proprietà statiche memorizzate. Questo è esattamente il motivo per cui sto postando questa domanda ... – Evert

+0

Forse puoi cambiare cache essere una variabile globale di tipo [AnyObject] e all'interno dei metodi EntityCollection trasmessi a [T]? – mikem

5

Non sono sicuro se mi piace questo ancora o no, ma ho usato una proprietà calcolata statica:

private extension Array where Element: String { 
    static var allIdentifiers: [String] { 
     get { 
      return ["String 1", "String 2"] 
     } 
    } 
} 

Pensieri?

+1

Questa sembra la soluzione più Swifty. Vorrei davvero che ci permettessero di usare costanti memorizzate, però. :/ –

+2

Penso che questo sarebbe compilare ma creare una nuova copia ogni volta e comportarsi come una proprietà non statica – pshah

2

Un'ora fa ho un problema simile al tuo. Voglio anche avere una classe BaseService e molti altri servizi ereditati da questa con una sola istanza statica. E il problema è che tutti i servizi usano il proprio modello (es: UserService usando UserModel ..)

In breve ho provato il seguente codice. E funziona !.

class BaseService<Model> where Model:BaseModel { 
    var models:[Model]?; 
} 

class UserService : BaseService<User> { 
    static let shared = UserService(); 

    private init() {} 
} 

Spero che sia d'aiuto.

Penso che il problema sia stato che lo stesso BaseService non verrà utilizzato direttamente, quindi NON È NECESSARIO AVERE proprietà statiche memorizzate. (P.S.Vorrei che swift supporti la classe astratta, BaseService dovrebbe essere)

+0

Che coincidenza! Finisco il problema con questa soluzione e poi vedo la tua risposta! : D – nahung89

0

Si scopre che, sebbene le proprietà non siano consentite, i metodi e le proprietà calcolate sono. Così si può fare qualcosa di simile:

class MyClass<T> { 
    static func myValue() -> String { return "MyValue" } 
} 

Oppure:

class MyClass<T> { 
    static var myValue: String { return "MyValue" } 
}