2

我正在尝试为我的应用程序创建一个通用错误处理程序并使事情变得更加复杂我正在使用事件总线来传递任务,因此我无法在编译时指定类型。我正在尝试执行以下操作:

let apiTask = data.object as! Task // Option 1
let apiTask = data.object as! Task<AnyObject> // Option 2

apiTask!.continueWith { (task) in
    if(task.cancelled || task.faulted) {
        self.isInError = true
    } else {
        self.isInError = false
    }
}

选项 1给出编译时错误,指出无法推断 Task 的泛型类型 TResut。 选项 2导致运行时错误说Task<SpecificType> cannot be caster to Task<AnyObject>

我在 Java 中有相同的实现,您似乎不需要在那里指定泛型类型。Task<TResult>可能是任何类型,所以我不能在上面的方法中指定它。有没有办法解决这个问题?

4

3 回答 3

3

听起来您实际上并不想要泛型类型。泛型类型的存在是为了在编译时准确地指定您试图擦除的类型信息。如果您几乎总是想忽略泛型参数,那么您应该创建一个非泛型类型。但是,如果您通常使用该信息,您仍然可以在某些方法中忽略它:您只需要将这些方法设为通用:

func doSomething<T>(to: Task<T>) {
    //Do whatever you want that doesn't involve `T`.
    //You still have to make this method generic so it accepts any type of `Task`.
}
于 2016-08-05T00:29:54.677 回答
0

您是否考虑过让 Task 成为协议(或符合协议)?

protocol Task {
    func execute()
}

class SimpleTask<T>: Task {
    let parameter: T
    init(parameter: T) {
        self.parameter = parameter
    }
    func execute() {
        print("executing task with parameter: \(parameter)")
    }
}

func executeTask(task: Task) {
    task.execute()
}

let simpleTask = SimpleTask<Int>(parameter: 1)
executeTask(simpleTask)
于 2016-08-05T01:42:25.787 回答
0

我在 Bolts-Swift 问题跟踪器上看到了您的帖子,由于我不知道您是否在那里看到我的答案,所以我想我也将其发布在这里。我是 Bolts 的新手,也是 Swift 的初学者,但我有几年的程序员经验,所以这是我想出的一个可能的解决方案:

我认为您可以创建一个类或结构来充当实际结果的包装器。这个结构/类只需要一个 AnyObject 类型的变量。然后,您将其用作任务的通用类型。稍后您可以对结果的类型进行精确检查,例如使用if let string = task.result?.result as? String{...}. 请参阅下面的代码以了解我的意思。

func printHelloWorld() {
    doSomething().continueWith() { task in
        print(task.result?.result)
    }
}

func doSomething() -> Task<MyResult> {
    let tcs = TaskCompletionSource<MyResult>()
    ...
    tcs.set(result: MyResult(result: "Hello World" as AnyObject))
    ...
    return tcs.task
}

struct MyResult {
    var result: AnyObject
}

正如我所说,我是 Bolts 和 Swift 的初学者,可能有更好的解决方案。如果您已经找到了更好的解决方案,也许您可​​以在此处发布并选择它作为您问题的答案。:)

于 2016-11-18T03:59:56.940 回答