首页 文章

符合协议的类作为Swift中的函数参数

提问于
浏览
72

在Objective-C中,可以将符合协议的类指定为方法参数 . 例如,我可以有一个方法只允许 UIViewController 符合 UITableViewDataSource

- (void)foo:(UIViewController<UITableViewDataSource> *)vc;

我可以't find a way to do this in Swift (perhaps it'不可能) . 您可以使用 func foo(obj: protocol<P1, P2>) 指定多个协议,但是如何要求对象也是特定类?

6 回答

  • 16

    Note in September 2015 :这是斯威夫特早期的观察 .

    这似乎是不可能的 . Apple也对他们的一些API有这种烦恼 . 以下是iOS 8中新引入的一个示例(从beta 5开始):

    UIInputViewControllertextDocumentProxy property :

    在Objective-C中定义如下:

    @property(nonatomic, readonly) NSObject<UITextDocumentProxy> *textDocumentProxy;
    

    在斯威夫特:

    var textDocumentProxy: NSObject! { get }
    

    链接到Apple的文档:https://developer.apple.com/library/prerelease/iOS/documentation/UIKit/Reference/UIInputViewController_Class/index.html#//apple_ref/occ/instp/UIInputViewController/textDocumentProxy

  • 0

    这个怎么样?:

    protocol MyProtocol {
        func getTableViewDataSource() -> UITableViewDataSource
        func getViewController() -> UIViewController
    }
    
    class MyVC : UIViewController, UITableViewDataSource, MyProtocol {
    
        // ...
    
        func getTableViewDataSource() -> UITableViewDataSource {
            return self
        }
    
        func getViewController() -> UIViewController {
            return self
        }
    }
    
    func foo(_ vc:MyProtocol) {
        vc.getTableViewDataSource() // working with UITableViewDataSource stuff
        vc.getViewController() // working with UIViewController stuff
    }
    
  • 0

    在Swift 4中,您可以通过新的&sign实现此目的:

    let vc: UIViewController & UITableViewDataSource
    
  • 106

    您可以将 foo 定义为泛型函数,并使用类型约束来同时要求类和协议 .

    Swift 4

    func foo<T: UIViewController & UITableViewDataSource>(vc: T) {
        .....
    }
    

    Swift 3 (适用于Swift 4)

    func foo<T: UIViewController>(vc:T) where T:UITableViewDataSource { 
        ....
    }
    

    Swift 2

    func foo<T: UIViewController where T: UITableViewDataSource>(vc: T) {
        // access UIViewController property
        let view = vc.view
        // call UITableViewDataSource method
        let sections = vc.numberOfSectionsInTableView?(tableView)
    }
    
  • 4

    Swift书籍文档建议您使用带有where子句的类型约束:

    func someFunction<C1: SomeClass where C1:SomeProtocol>(inParam: C1) {}
    

    这保证了“inParam”的类型为“SomeClass”,条件是它也遵循“SomeProtocol” . 您甚至可以指定逗号分隔的多个where子句:

    func itemsMatch<C1: SomeProtocol, C2: SomeProtocol where C1.ItemType == C2.ItemType,    C1.ItemType: SomeOtherProtocol>(foo: C1, bar: C2) -> Bool { return true }
    
  • 17

    使用Swift 3,您可以执行以下操作:

    func foo(_ dataSource: UITableViewDataSource) {
        self.tableView.dataSource = dataSource
    }
    
    func foo(_ delegateAndDataSource: UITableViewDelegate & UITableViewDataSource) { 
        //Whatever
    }
    

相关问题