Class conforming to protocol as function parameter in Swift

前端 未结 7 1245
萌比男神i
萌比男神i 2020-11-29 02:12

In Objective-C, it\'s possible to specify a class conforming to a protocol as a method parameter. For example, I could have a method that only allows a UIViewControlle

相关标签:
7条回答
  • 2020-11-29 02:35

    The Swift book documentation suggests that you use type constraints with a where clause:

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

    This guarantees that "inParam" is of type "SomeClass" with a condition that it also adheres to "SomeProtocol". You even have the power to specify multiple where clauses delimited by a comma:

    func itemsMatch<C1: SomeProtocol, C2: SomeProtocol where C1.ItemType == C2.ItemType,    C1.ItemType: SomeOtherProtocol>(foo: C1, bar: C2) -> Bool { return true }
    
    0 讨论(0)
  • 2020-11-29 02:43

    You can define foo as a generic function and use type constraints to require both a class and a protocol.

    Swift 4

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

    Swift 3 (works for Swift 4 also)

    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)
    }
    
    0 讨论(0)
  • 2020-11-29 02:44

    In Swift 4 you can achieve this with the new & sign:

    let vc: UIViewController & UITableViewDataSource
    
    0 讨论(0)
  • 2020-11-29 02:48

    Note in September 2015: This was an observation in the early days of Swift.

    It seems to be impossible. Apple has this annoyance in some of their APIs as well. Here is one example from a newly introduced class in iOS 8 (as of beta 5):

    UIInputViewController's textDocumentProxy property:

    Defined in Objective-C as follows:

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

    and in Swift:

    var textDocumentProxy: NSObject! { get }
    

    Link to Apple' documentation: https://developer.apple.com/library/prerelease/iOS/documentation/UIKit/Reference/UIInputViewController_Class/index.html#//apple_ref/occ/instp/UIInputViewController/textDocumentProxy

    0 讨论(0)
  • Swift 5:

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

    So essentially Jeroen's answer above.

    0 讨论(0)
  • 2020-11-29 02:51

    With Swift 3, you can do the following:

    func foo(_ dataSource: UITableViewDataSource) {
        self.tableView.dataSource = dataSource
    }
    
    func foo(_ delegateAndDataSource: UITableViewDelegate & UITableViewDataSource) { 
        //Whatever
    }
    
    0 讨论(0)
提交回复
热议问题