2014-09-29 12 views
8

Oggi ho riscontrato un problema strano quando stavo cercando di "generalizzare" le mie "operazioni di importazione CoreData". Sembra che se creo una sottoclasse generica di NSOperation, la funzione main() non verrà chiamata.La sottoclasse NSOperation generica perde la funzionalità NSOperation

semplice esempio:

class MyOperation<T: NSObject>: NSOperation { 

    override func main() { 
     println("My operation main was called") 
    } 
} 

Se si crea un'istanza di questa classe e aggiungerlo alla operationQueue si vedrà che è main() non è effettivamente chiamato.

override func viewDidLoad() { 
    super.viewDidLoad() 
    // Do any additional setup after loading the view, typically from a nib. 

    self.operationQueue = NSOperationQueue() 
    let operation = MyOperation<NSString>() 
    self.operationQueue!.addOperation(operation) 
} 

Operazione transita semplicemente ready-executing e finished stato senza chiamare main().

Se rimuovo l'annotazione generica <T: NSObject> dalla classe MyOperation funzionerà correttamente.

Com'è possibile? Mi manca qualcosa qui?

risposta

7

Il problema è causato da questa semplice regola:

metodo in una classe generica non può essere rappresentato in Objective-C

Di conseguenza, quando ponte di Objective-C, MyOperation sguardi come puro, senza metodi sono sovrascritti, sottoclasse NSOperation.

È possibile visualizzare questo errore contrassegnando override func main() con l'attributo @objc.

@objc override func main() { // < [!] Method in a generic class cannot be represented in Objective-C 
    println("My operation main was called") 
} 
+1

Grazie per chiarimenti. È triste che non possiamo usare una tecnica così potente in Swift con Objective-C. In questo caso particolare, le operazioni "generalizzate" potrebbero aiutare a riutilizzare un bel po 'di codice. Bene sì. :/ – Nevs12

12

Soluzione alternativa: è possibile creare NSOperation sottoclasse (generici), ignorare principale e chiamare il proprietario di 'eseguire' func, che può essere ignorato dalle sottoclassi generiche. Esempio:

class SwiftOperation : NSOperation { 

    final override func main() { 
     execute() 
    } 

    func execute() { 
    } 

} 

class MyOperation<T> : SwiftOperation { 

    override func execute() { 
     println("My operation main was called") 
    } 

} 
+0

Fantastico, grazie! Molto utile anche per i delegati UIKit! – Ixx

+0

Io uso questo metodo per implementare un tableViewDataSource generico – banxi1988

1

In Xcode 7 generico NSOperation è stato risolto: se corro questo codice in un parco giochi funziona:

protocol SomeProtocol { 

    // markup protocol 
} 

class GenericOperation<SomeTypeImplementingProtocol: SomeProtocol>: NSOperation { 

    let referenceToSomeTypeImplementingProtocol: SomeTypeImplementingProtocol 

    init(referenceToSomeTypeImplementingProtocol: SomeTypeImplementingProtocol) { 

     self.referenceToSomeTypeImplementingProtocol = referenceToSomeTypeImplementingProtocol 
    } 

    override func main() { 

     debugPrint("The GenericOperation main() method was called.") 

    } 
} 

class TypeImplementingSomeProtocol: SomeProtocol { 


    init() { 

    } 
} 


let operationQueue = NSOperationQueue() 

let typeImplementingSomeProtocolInstance = TypeImplementingSomeProtocol() 


let operation = GenericOperation<TypeImplementingSomeProtocol>(referenceToSomeTypeImplementingProtocol: typeImplementingSomeProtocolInstance) 


operationQueue.addOperation(operation) 
Problemi correlati