通用的NSOperation子类失去了NSOperation的功能

9
今天在尝试“泛化”我的“CoreData导入操作”时,遇到了一个奇怪的问题。发现如果我创建一个NSOperation的通用子类,则main()函数将不会被调用。
简单示例:
class MyOperation<T: NSObject>: NSOperation {

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

如果您创建此类的实例并将其添加到operationQueue中,则会发现其main()实际上并未被调用。
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)
}

操作简单地从ready转换到executing再到finished状态,而不会调用main()

如果我从MyOperation类中删除泛型注释<T: NSObject>,它将正常工作。

这是如何可能的?我错过了什么吗?

3个回答

12

解决方法:您可以创建NSOperation子类(非通用),覆盖main并调用自己的'execute'函数,这可以被通用子类重写。 示例:

Workaround: 您可以创建NSOperation子类(非通用),覆盖main并调用自己的'execute'函数,这可以被通用子类重写。 示例:

class SwiftOperation : NSOperation {

    final override func main() {
        execute()
    }

    func execute() {
    }

}

class MyOperation<T> : SwiftOperation {

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

}

太棒了,谢谢!非常有用,也适用于UIKit的代理! - User
我使用这种方法来实现通用的tableViewDataSource。 - banxi1988

7

这个问题是由于这条简单的规则引起的:

通用类中的方法无法在Objective-C中被表示

因此,当桥接到Objective-C时,MyOperation看起来像纯粹的NSOperation子类,没有任何方法被覆盖。

您可以通过使用@objc属性标记override func main()来查看此错误。

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

2
感谢您的澄清。很遗憾我们不能在Swift中使用Objective-C这么强大的技术。在这种情况下,“泛化”操作可以帮助我们重用相当多的代码。嗯,是啊。 :/ - Nevs12

1
在Xcode 7中,通用的NSOperation已经被修复:如果我在playground中运行此代码,则可以正常工作:
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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接