标签: swift-protocols

使swift类符合协议 - 在静态/类级别

我正在尝试在Swift中构建一个通用的UITableViewController子类,它可以容纳任意数量的不同类型的表视图单元,而不具备任何内部知识.

要做到这一点,我正在尝试为我的模型和我的表视图单元格使用协议.模型的协议将返回我应该去的哪个单元类,并且单元的协议将返回问题的答案,例如给定模型的单元格高度应该是什么.

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

模型的协议如下:

protocol JBSTableItemDelegate
{
    func tableCellDelegate() -> JBSTableViewCellInterface
}
Run Code Online (Sandbox Code Playgroud)

细胞的协议如下:

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
}
Run Code Online (Sandbox Code Playgroud)

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

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

let tableViewCellInterface = tableItem!.tableViewCellInterface()
Run Code Online (Sandbox Code Playgroud)

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

func tableViewCellInterface() -> JBSTableViewCellInterface
{
    return JBSLiteratureTableViewCell.self as! JBSTableViewCellInterface
}
Run Code Online (Sandbox Code Playgroud)

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

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

returnFloat = tableViewCellInterface.tableView(tableView, heightForRowAtIndexPath: indexPath, tableItem: tableItem!)
Run Code Online (Sandbox Code Playgroud)

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

'JBSTableViewCellInterface'没有名为'tableView'的成员

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

'JBSLiteratureTableViewCell'不符合协议'JBSTableViewCellInterface'

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

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

protocols ios swift swift-protocols

6
推荐指数
1
解决办法
1818
查看次数

测试协议与相关类型的一致性

我有一个使用关联类型的协议,如下所示:

protocol Populatable {
    typealias T
    func populateWith(object: T)
}
Run Code Online (Sandbox Code Playgroud)

和实现协议的类:

class DateRowType: Populatable {
    func populateWith(object: NSDate) {
        print(object.description)
    }
}

class StringRowType : Populatable {
    func populateWith(object: String) {
        print(object)
    }
}
Run Code Online (Sandbox Code Playgroud)

但是当我尝试投射或测试一致性时,像这样:

let drt = DateRowType()
let srt = StringRowType()

let rowTypes = [drt, srt]
let data = [NSDate(), "foo"]

for (i, p: Populatable) in enumerate(rowTypes) {
    p.populateWith(data[i])
}
Run Code Online (Sandbox Code Playgroud)

我收到错误:

Protocol'Populatable'只能用作通用约束,因为它具有Self或相关类型要求

测试对象是否符合Populatable协议的正确方法是什么?

注意:尝试此操作所需的所有代码都包含在问题中,只需将代码块复制到操场中即可.

generics swift swift-protocols

6
推荐指数
1
解决办法
523
查看次数

扩展UICollectionViewDataSource协议以添加默认实现

我有一个相当大的应用程序,它有很多集合视图.大多数集合视图都具有相同的数据源和流布局代表(相同的大小,边距等)的实现.我正在尝试创建一个提供UICollectionViewDataSource和UICollectionViewDelegateFlowLayout的默认实现的协议.这是我的代码.

protocol TiledCollectionView{}

extension UICollectionViewDataSource where Self: TiledCollectionView{
    //default implementation of the 3 methods to load the data ...
}
extension UICollectionViewDelegateFlowLayout where Self: TiledCollectionView {
    //default implementation for layout methods to set default margins etc...
}

class MyViewController: UIViewController, TiledCollectionView, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout{
    // the rest of the required logic for view controller
    // here I Don't implement any CollectionView methods since I have provided the default implementation already
}
Run Code Online (Sandbox Code Playgroud)

问题是,编译器抱怨MyViewController不符合UICollectionViewDataSource.这不应该是这种情况,因为我清楚地说,如果类型是TiledCollectionView,则添加默认实现.

有人可以帮忙吗?

uicollectionview swift swift-extensions swift-protocols protocol-extension

6
推荐指数
1
解决办法
3184
查看次数

从协议扩展实例方法中读取静态var

假设我们有一个Swift协议:

protocol SomeProtocol: class {
    static var someString: String { get }
}
Run Code Online (Sandbox Code Playgroud)

有没有办法someString从扩展实例方法访问,像这样?

extension SomeProtocol {
    public func doSomething() -> String {
        return "I'm a \(someString)"
    }
}
Run Code Online (Sandbox Code Playgroud)

我收到编译器错误:

静态成员'someString'不能用于'Self'类型的实例

有没有办法实现这个目标?

swift swift-protocols

6
推荐指数
1
解决办法
913
查看次数

在Xcode中看到为什么"类型不符合协议"(swift)

我经常有相对复杂的协议与associatedType约束,在泛型中使用,由CoreData类型扩展使用等.因此我经常得到错误:Type .. does not conform to protocol ....我通常可以在一段时间后弄清楚这一点,但错误信息实际上是无益的 - 通常,如果问题是方法或某事的签名中的一个小错误,则该bug需要一段时间才能找到.使用Java接口,IDE通常会报告类似的内容method ... not implemented,因此我知道要更详细地查看哪种方法.

有没有办法让Xcode报告有关协议成员的详细信息?

xcode ios swift swift-protocols

6
推荐指数
1
解决办法
6859
查看次数

比较2个结构/对象实现相同的协议?

假设我有以下内容:

protocol P : Equatable {
 var uniqueID : Int { get }
}

struct A : P {
 var uniqueID = 1
}

struct B : P {
 var uniqueID = 2
}

func ==<T : P>(lhs:T , rhs:T) -> Bool { return lhs.uniqueID == rhs.uniqueID }
Run Code Online (Sandbox Code Playgroud)

现在,当我写下以下内容时:

 let a = A()
 let b = B()

 let c = a == b
Run Code Online (Sandbox Code Playgroud)

我收到错误:二元运算符'=='不能应用于'A'和'B'类型的操作数

有没有办法实现这个目标?

protocols swift swift-protocols

6
推荐指数
1
解决办法
751
查看次数

将协议和符合类(!)实例作为参数的函数

我试图弄清楚如何定义一个采用以下两个参数的函数:

  1. 协议.
  2. 符合该协议的(引用类型)的实例.

例如,给定

protocol P { }
class C : P { } // Class, conforming to P
class D { }     // Class, not conforming to P
struct E: P { } // Struct, conforming to P
Run Code Online (Sandbox Code Playgroud)

这应该编译:

register(P.self, obj: C()) // (1)
Run Code Online (Sandbox Code Playgroud)

但这些不应该编译:

register(P.self, obj: D()) // (2)  D does not conform to P
register(P.self, obj: E()) // (3)  E is not a class
Run Code Online (Sandbox Code Playgroud)

如果我们放弃第二个参数是类实例的条件,这很容易:

func register<T>(proto: T.Type, obj: T) {
    // ... …
Run Code Online (Sandbox Code Playgroud)

generics swift swift-protocols

6
推荐指数
1
解决办法
674
查看次数

Swift协议函数:返回相同类型的符合类

我想知道是否可以在Swift中完成类似java(或c ++)的事情:

我有一个协议:

protocol Prot1 {
   func returnMyself() -> Prot1
}
Run Code Online (Sandbox Code Playgroud)

一个类符合协议Prot1.我可以强制函数的返回类型returnMyself()与下面的类的类型相同吗?

class MyClass: Prot1 {
   public func returnMyself() -> MyClass {
      return self
   }
}
Run Code Online (Sandbox Code Playgroud)

可能吗?

swift swift-protocols

6
推荐指数
1
解决办法
699
查看次数

Swift协议继承

我有快速的代码:

protocol ParentProtocol {
    // stuff
}

protocol ChildProtocol: ParentProtocol {
    // additional stuff
}

protocol FooProtocol {
    var variable: ParentProtocol? { get }
}

class Foo:FooProtocol {
    var variable: ChildProtocol?
}
Run Code Online (Sandbox Code Playgroud)

我有编译器错误:

类型'Foo'不符合协议'FooProtocol'

我知道,根据FooProtocol,变量类型必须是ParentProtocol类型.另一方面ChildProtocol继承自ParentProtocol,所以它也是一个ParentProtocol

是否有任何解决方案以这种方式使用协议继承?

swift swift-protocols

6
推荐指数
1
解决办法
4104
查看次数

在两个不同的类中实现UITableViewDataSource协议

我不确定这可以做到,或者甚至不推荐.

我想要实现的目标如下:

我有一个2类,classA并且classB引用了同一个UITableview实例.我想要的是负责协议classA的2个必要方法的实现UITableViewDataSource:

  • numberOfRowsInSection
  • cellForRowAt

然后我希望classB能够实现其他可选方法titleForHeaderInSection,例如.

那么如何才能classA有一些协议方法的默认实现,让我们classB成为一个可以在classB已经完成的基础上构建的类?

在某种程度上,我面临的问题如下:多个类如何成为单个数据源UITableView

编辑: classA将在我正在编写的库中,负责构建tableView的核心部分.classB将由第三方开发人员用于主要定制其外观.

protocols uitableview ios swift swift-protocols

6
推荐指数
1
解决办法
1301
查看次数