6

我正在尝试在 Swift 中构建一个通用的 UITableViewController 子类,它可以容纳任意数量的不同类型的表格视图单元格,而无需了解它们中的任何一个。

为此,我尝试为我的模型和表格视图单元格使用协议。模型的协议将返回我应该去哪个单元格类别,而单元格的协议将返回对给定模型的单元格高度应该是多少等问题的答案。

但是我在使协议工作时遇到问题,因为使用第二个协议我想进入单元的类而不是它的实例。

模型的协议如下:

protocol JBSTableItemDelegate
{
    func tableCellDelegate() -> JBSTableViewCellInterface
}

细胞的协议如下:

protocol JBSTableViewCellInterface: class
{
    static func registerNibsWithTableView(tableView: UITableView)

    static func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath?, tableItem: JBSTableItemDelegate) -> CGFloat

    static func tableView(tableView: UITableView, dequeueReusableCellWithIndexPath indexPath: NSIndexPath, tableItem: JBSTableItemDelegate, delegate: AnyObject) -> JBSTableViewCell
}

注意关键字“static”的使用。这些方法是 UITableViewCell 子类中的类方法,添加静态似乎是我需要做的来验证这些类是否符合,或者我理解。

当我使用第一个协议时,代码看起来像这样,它编译:

let tableViewCellInterface = tableItem!.tableViewCellInterface()

它正在调用此方法(作为一个示例):

func tableViewCellInterface() -> JBSTableViewCellInterface
{
    return JBSLiteratureTableViewCell.self as! JBSTableViewCellInterface
}

这将返回单元格的类,例如“JBSLiteratureTableViewCell.self”

当我使用第二个协议时,代码看起来像这样,并且无法编译:

returnFloat = tableViewCellInterface.tableView(tableView, heightForRowAtIndexPath: indexPath, tableItem: tableItem!)

由于之前的 static 关键字,它无法编译,我得到的编译器错误是:

“JBSTableViewCellInterface”没有名为“tableView”的成员

如果我从协议函数中取出静态关键字,它会编译,但是 UITableViewCell 子类抱怨说:

“JBSLiteratureTableViewCell”不符合协议“JBSTableViewCellInterface”

这是因为他们现在正试图确保实例方法存在,而这些方法并不存在。

如何使 swift 类符合类级别的协议,所以它可以是我的委托而不是类的某个实例?我确信我可以通过创建作为单例的协议 JBSTableViewCellInterface 的帮助程序类并让它们完成工作来解决这个问题,但我宁愿将它直接构建到其类方法中的 UITableViewCell 子类中。

4

2 回答 2

5

已针对 Swift 2.0 及更高版本更新

根据 Gregzo 的回答,Swift 2.0+ 允许在协议定义中将方法声明为静态。这些必须满足实现协议的对象中的静态/类方法。

您不能使用静态方法满足实例方法的协议定义,反之亦然,这使得对于上述问题的回答不完整。

如果您想尝试这样做,只需在协议定义中使用关键字“static”来实现您将在符合对象中作为静态或类方法实现的方法:

protocol InstanceVsStatic {
    func someInstanceFunc()
    static func someStaticFunc()
}

enum MyConformingEnum: InstanceVsStatic {
    case someCase

    static func someStaticFunc() {
           // code
    }
    func someInstanceFunc() {
        // code
    }
}

class MyConformingClass: InstanceVsStatic {
    class func someStaticFunc() {
           // code
    }
    func someInstanceFunc() {
        // code
    }
}

struct MyConformingStruct: InstanceVsStatic {
    static func someStaticFunc() {
           // code
    }
    func someInstanceFunc() {
        // code
    }
}

您可以让实例方法调用静态/类方法:

这允许您在需要符合需要实例方法的协议时执行静态代码。

struct MyConformingStruct: InstanceVsStatic {
    static func doStuffStatically(){
        // code
    }

    static func someStaticFunc() {
           // code
    }

    func someInstanceFunc() {
        MyConformingStruct.doStuffStatically()
    }
}

斯威夫特 1.2

除了上面的间接方式,没有办法使用静态(类)方法来符合纯 swift 版本 1.2 及以下版本中的协议。这是一个已知的错误/未实现的功能:https ://openradar.appspot.com/20119848

于 2015-06-10T06:16:30.733 回答
2

如果协议 func 是静态的,则实现者应将其实现为静态方法,如果不是,则将其实现为实例方法:

protocol MixedProtocol
{
    static func staticFoo()
    func instanceBar()
}

class ExampleClass : MixedProtocol
{
    // implementing static func as class func is fine.
    // class funcs are overridable, not static ones
    class func staticFoo()
    {
        println( "I'm a class func" )
    }

    func instanceBar()
    {
        println( "I'm an instance func" )
    }
}

没有直截了当的方法:遵守协议就意味着,“静态”是协议成员声明的关键特性,实现者必须尊重。

于 2015-04-18T08:08:58.340 回答