简体   繁体   English

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

[英]Implement delegate using generic protocol in Swift

I'm trying to create a delegate protocol that implements a function which passes an array of a generic type. 我正在尝试创建一个委托协议,该协议实现一个传递泛型类型数组的函数。 I've tried several combinations but none of them seem to do the trick. 我已经尝试了几种组合,但似乎没有一种组合。

This is the most approximate thing i've reached to. 这是我达成的最近似的事情。 This is the protocol: 这是协议:

     protocol APIControllerProtocol {

          typealias T

          func didReceiveAPIResults(results: [T])
     }

And this is the the delegator object: 这是委托者对象:

    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)})

         }

     }

However, the last line get this error: "Album is not convertible to UT" 但是,最后一行出现此错误:“相册无法转换为UT”

"Album" is the model object used to return the results. “Album”是用于返回结果的模型对象。

What am i doing wrong? 我究竟做错了什么?

EDIT: 编辑:

Following Mike S advice , i've made the protocol method didReceiveAPIResults a generic function, and specified what T is in the delegate. 按照Mike S的建议 ,我已经将协议方法didReceiveAPIResults作为通用函数,并指定了委托中的T However, when receiving and assigning the argument of type T to a property in the delegate, i get the error: "T is not identical to T" 但是,当接收并将类型T的参数分配给委托中的属性时,我得到错误:“T与T不相同”

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"
    }
}

Your didReceiveAPIResults declaration in APIControllerProtocol needs to be a generic function so that the generic type T is passed along to it correctly. didReceiveAPIResults在声明APIControllerProtocol需要使泛型类型是一个泛型函数T沿着它正确地传递。

protocol APIControllerProtocol {
    typealias T

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

Note: This means your delegate definition will need to define what T is: 注意:这意味着您的委托定义需要定义T是什么:

class TestDelegate: APIControllerProtocol {
    typealias T = Album

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

Update: While the code above does get rid of the original error, it turns out that it acts more like a workaround and doesn't really address the root of the problem. 更新:虽然上面的代码确实摆脱了原始错误,但事实证明它更像是一种解决方法,并没有真正解决问题的根源。

The real issue seems to be that the compiler is having trouble reconciling what UT is with no ambiguity. 真正的问题似乎是编译器无法协调UT是什么,没有歧义。 That's actually easy enough to fix though, we just need to give it a more precise definition (note the where clause in the APIController definition) : 这实际上很容易修复,我们只需要给它一个更精确的定义(注意APIController定义中的where子句)

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

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

Note: I removed the <T> that I added to the function in the protocol previously; 注意:我删除了之前添加到协议中的函数的<T> ; that's not needed anymore and will end up causing problems later. 这不再需要了,最终会导致问题。

With that, the TestDelegate class works as expected (you don't even need the typealias anymore): 有了它, TestDelegate类按预期工作(你甚至不再需要typealias ):

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM