在Objective-C中,可以将符合协议的类指定为方法参数。例如,我可以有一个只允许UIViewController
符合的方法UITableViewDataSource
:
- (void)foo:(UIViewController<UITableViewDataSource> *)vc;
我找不到在Swift中执行此操作的方法(也许尚不可能)。您可以使用来指定多个协议func foo(obj: protocol<P1, P2>)
,但是您又如何要求该对象属于特定类呢?
在Objective-C中,可以将符合协议的类指定为方法参数。例如,我可以有一个只允许UIViewController
符合的方法UITableViewDataSource
:
- (void)foo:(UIViewController<UITableViewDataSource> *)vc;
我找不到在Swift中执行此操作的方法(也许尚不可能)。您可以使用来指定多个协议func foo(obj: protocol<P1, P2>)
,但是您又如何要求该对象属于特定类呢?
Answers:
您可以将其定义foo
为通用函数,并使用类型约束来同时要求类和协议。
斯威夫特4
func foo<T: UIViewController & UITableViewDataSource>(vc: T) {
.....
}
Swift 3(也适用于Swift 4)
func foo<T: UIViewController>(vc:T) where T:UITableViewDataSource {
....
}
迅捷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)
}
protocol<>
提供更简洁的语法,例如Provides(但protocol<>
不能包含非协议类型)。
numberOfSectionsInTableView
因为它是其中的必需功能UITableViewDataSource
?
numberOfSectionsInTableView:
是可选的-您可能会想到tableView:numberOfRowsInSection:
。
func foo<T: UIViewController>(vc:T) where T:UITableViewDataSource { ... }
在Swift 4中,您可以使用新的&符号实现此目的:
let vc: UIViewController & UITableViewDataSource
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 }
使用Swift 3,您可以执行以下操作:
func foo(_ dataSource: UITableViewDataSource) {
self.tableView.dataSource = dataSource
}
func foo(_ delegateAndDataSource: UITableViewDelegate & UITableViewDataSource) {
//Whatever
}
这样呢?:
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
}
2015年9月的注意事项:这是Swift早期的观察结果。
这似乎是不可能的。苹果在某些API中也有这种烦恼。这是iOS 8(自Beta 5起)中新引入的类的一个示例:
UIInputViewController
的textDocumentProxy
属性:
在Objective-C中定义如下:
@property(nonatomic, readonly) NSObject<UITextDocumentProxy> *textDocumentProxy;
在Swift中:
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
var textDocumentProxy: UITextDocumentProxy! { get }
@protocol MyAwesomeCallbacks <NSObject>