在Swift中使用通用协议实现委托

时间:2014-09-08 20:36:35

标签: ios swift

我试图创建一个委托协议来实现一个传递泛型类型数组的函数。我尝试了几种组合,但似乎没有一种组合。

这是我达成的最近似的事情。这是协议:

     protocol APIControllerProtocol {

          typealias T

          func didReceiveAPIResults(results: [T])
     }

这是委托人对象:

    class APIController<U:APIControllerProtocol> {

         typealias ElementType = U
         var delegate: ElementType?

         init(delegate: ElementType){

             self.delegate = delegate

         }

         func getAPIResults(){

              // Perform some action before delegation
              // "results" is an Array of dictionaries got from NSJSONSerialization

              self.delegate?.didReceiveAPIResults(results.map{dict in Album(json:dict)})

         }

     }

但是,最后一行会收到此错误:&#34;专辑无法转换为U.T&#34;

&#34;相册&#34;是用于返回结果的模型对象。

我做错了什么?

修改

Mike S advice之后,我已经将协议方法didReceiveAPIResults作为通用函数,并指定了T在委托中的内容。但是,当接收并将类型T的参数分配给委托中的属性时,我得到错误:&#34; T与T&#34;

不同
class TestDelegate: APIControllerProtocol {
    typealias T = Album
    var albums:[T] = [T]()

    func didReceiveAPIResults<T>(results: [T]) {
        // ...

        self.albums = results //ERROR: "T is not identical to T"
    }
}

1 个答案:

答案 0 :(得分:1)

didReceiveAPIResults中的APIControllerProtocol声明需要是通用函数,以便将通用类型T正确传递给它。

protocol APIControllerProtocol {
    typealias T

    func didReceiveAPIResults<T>(results: [T])
}

注意:这意味着您的委托定义需要定义T是什么:

class TestDelegate: APIControllerProtocol {
    typealias T = Album

    func didReceiveAPIResults<T>(results: [T]) {
        // ...
    }
}

更新:虽然上面的代码确实摆脱了原始错误,但事实证明它更像是一种解决方法,并没有真正解决问题的根源。 / em>的

真正的问题似乎是编译器无法协调U.T没有含糊不清的内容。这实际上很容易修复,我们只需要给它一个更精确的定义(注意where定义中的APIController子句)

protocol APIControllerProtocol {
    typealias T
    func didReceiveAPIResults(results: [T])
}

class APIController<U:APIControllerProtocol where U.T == Album> {
    typealias ElementType = U
    // ...
}

注意:我删除了之前添加到协议中的函数的<T>;这不再需要了,最后会导致问题。

这样,TestDelegate类按预期工作(您甚至不再需要typealias):

class TestDelegate: APIControllerProtocol {
    var albums: [Album]? = nil

    func didReceiveAPIResults(results: [Album]) {
        albums = results
    }
}