我试图在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
}
注意关键字“静态”的用法。这些方法是UITableViewCell子类中的类方法,添加静态似乎是我需要做的工作,以验证这些类是否符合,或者我理解。
当我使用第一个协议时,代码看起来是这样的,它编译:
let tableViewCellInterface = tableItem!.tableViewCellInterface()
它调用此方法(例如):
func tableViewCellInterface() -> JBSTableViewCellInterface
{
return JBSLiteratureTableViewCell.self as! JBSTableViewCellInterface
}
这将返回单元格的类,如"JBSLiteratureTableViewCell.self“
当我使用第二个协议时,代码看起来是这样的,而且它没有编译:
returnFloat = tableViewCellInterface.tableView(tableView, heightForRowAtIndexPath: indexPath, tableItem: tableItem!)
由于前面的静态关键字up,它无法编译,我得到的编译器错误是:
'JBSTableViewCellInterface‘没有一个名为'tableView’的成员
如果我将静态关键字从协议函数中删除,它会编译,但是UITableViewCell子类会抱怨说:
'JBSLiteratureTableViewCell‘不符合'JBSTableViewCellInterface’协议
这是因为他们现在正试图确保实例方法的存在,而这些方法并不在这些方法中。
如何使快速类在类级别上符合协议,以便它可以是我的委托而不是类的某些实例?我确信我可以通过创建协议JBSTableViewCellInterface的助手类来解决这个问题,这些类是单例的,并让他们来完成这项工作,但是我更愿意将其构建到类方法中的UITableViewCell子类中。
发布于 2015-06-09 22:16:30
更新为Swift 2.0及以上版本的
根据Gregzo的答案,Swift 2.0+允许在协议定义中将方法声明为静态的。这些必须满足于实现协议的对象中的静态/类方法。
您不能用静态方法满足实例方法的协议定义,反之亦然,这使得上述问题的答案不完整。
如果您想尝试这一点,只需在您的协议定义中使用关键字“静态”作为方法的关键字,您将在符合条件的对象中实现为静态方法或类方法:
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()
}
}
Swift 1.2
除了上述间接的方法之外,没有办法使用静态(类)方法来遵从纯快速版本1.2及更低版本的协议。这是一个已知的错误/未实现的特性:https://openradar.appspot.com/20119848
发布于 2015-04-18 00:08:58
如果协议功能是静态的,则实现者应该将其实现为静态方法,如果不是,则作为实例方法实现:
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" )
}
}
没有直接的方法可以绕过它:遵守协议就意味着这一点,而“静态”是协议成员声明的一个关键特性,实现者必须遵守。
https://stackoverflow.com/questions/29711935
复制