Swift 泛型和协议扩展

Posted

技术标签:

【中文标题】Swift 泛型和协议扩展【英文标题】:Swift Generics and Protocol Extensions 【发布时间】:2015-09-20 19:57:01 【问题描述】:

我有一个协议Reusable,它有一个静态函数static func reuseId() -> String 和一个定义函数默认实现的协议扩展。然后,我在UITableViewCell 上实现了一个扩展,以符合Reusable 协议。我现在可以毫无问题地在 TableViewCells 上使用该函数:SomeTableViewCell.reuseId()

我遇到的问题是泛型。我有一个泛型类,它具有UITableViewCell 类型的泛型参数:

internal class SomeClass<CellType: UITableViewCell>: NSObject  
    ...

我希望能够在CellType 的泛型类中使用Reusable 中指定的函数,但不幸的是,这不能按预期工作。编译器总是生成错误Type 'CellType' has no member 'reuseId'

有人知道为什么会这样吗?有解决办法吗?

我正在使用 Xcode 7.0 和 Swift 2.0。

来自德国的问候

更新:这里有一些示例代码可以更好地显示我的问题:

import UIKit

protocol Reusable 
    static func reuseId() -> String


extension Reusable 
    static func reuseId() -> String 
        return String(self).componentsSeparatedByString(".").last!
    


extension UITableViewCell: Reusable  

class SomeGenericClass<CellType: UITableViewCell> 
    func someFunction() 
        let reuseIdentifier = CellType.reuseId()
    

此代码会产生上述错误,但我不太明白为什么会发生这种情况。我认为 jtbandes 发布的示例代码的主要区别在于我使用了静态函数。


更新:该问题在 Xcode 8.3 beta 2 中得到修复。上面的示例代码现在可以按预期工作(当然是在将其迁移到 Swift 3 之后)。

【问题讨论】:

如果您发布实际代码的(最小)示例而不是仅描述问题,将会更有帮助。 我在原始问题中添加了示例代码,希望可以让我的问题更容易理解。 【参考方案1】:

这是一个有趣的问题。您的代码似乎应该可以工作;你可能想file an enhancement request。

这是一个似乎可以正常工作的解决方法:

class SomeGenericClass<CellType: Cell> 
    func someFunction() 
        let reuseIdentifier = (CellType.self as Reusable.Type).reuseId()
    

【讨论】:

但是 CellType 继承自 UITableViewCell 已经符合 Reusable。在我看来,需要更多信息,我无法通过一个简单的示例重现该问题。 谢谢@MartinR,我想我误读了这个问题。是的,需要更多信息... 谢谢。我发布了一个雷达 22776964。您的解决方法似乎暂时可以正常工作,因此我会将您的答案标记为正确。一旦 Apple 回应雷达,我将更新问题。【参考方案2】:

获得所需内容的另一种(解决方法)方法:

class GenericExample<CellType:UITableViewCell where CellType:Reusable>     

    func test() -> String 
        return CellType.reuseId()
    


GenericExample<UITableViewCell>().test() // returns "UITableViewCell"
GenericExample<MyCell>().test() // returns "MyCell"

【讨论】:

PS 原始场景很可能是一个错误,因为 XCode 中的自动完成模型知道 CellType 有一个 resuseID() 但编译器会抱怨否则

以上是关于Swift 泛型和协议扩展的主要内容,如果未能解决你的问题,请参考以下文章

NSManagedObjectContext 扩展中泛型函数中的奇怪 Swift 行为

扩展类型的泛型和 Typescript 中的普通类型有啥区别?

使用C#中的自定义数据模型实现泛型和扩展ObservableCollection方法

泛型和枚举

Swift-扩展(Extensions)(十八)

Swift-扩展(Extensions)(十八)