我希望定义一个变量,它的类型为UIViewController
,并符合P1
协议。
问题:
- 我应该修改协议还是v1类型?
- 我应该如何做到这一点?
代码:
protocol P1 {
func f1();
}
var v1 : P1 //But needs to be a UIViewController which conforms to `P1`
在 Swift 4 中,您可以使用新的“&”符号创建符合协议和类的变量,其语法如下:
let vc: UIViewController & P1
从Swift 4开始:
多亏了SE-0156:
The proposal keeps the existing
&
syntax but allows one of the elements to be eitherAnyObject
or of class type. The equivalent to the above Objective-C types would look like this:AnyObject & Protocol1 & Protocol2 Base & Protocol
As in Objective-C, the first line is an existential of classes which conform to
Protocol1
andProtocol2
, and the second line is an existential of subtypes ofBase
which conform toProtocol
.
我们现在可以声明:
var v1 : UIViewController & P1 // UIViewController which conforms to `P1`
Swift 4之前:
没有直接的方法来实现这一点。你必须将v1
声明为UIViewController
或P1
,然后使用强制转换(as
)来获取其他功能。
最接近你想要的是使用泛型。例如:
func testGeneric<T: UIViewController where T: P1>(input: T) {
input.f1()
}
protocol Delegate: class {
func doDelegate()
}
class Controller {
func doController() {
print("Controller")
}
}
class ConcreteController: Controller, Delegate {
func doDelegate() {
print("Delegate")
}
}
class View {
private weak var controller: Controller? = nil
private weak var delegate: Delegate? = nil
func setDelegateController<T: Controller where T: Delegate>(delegateController: T?) {
controller = delegateController
delegate = delegateController
}
func test() {
controller?.doController()
delegate?.doDelegate()
}
}
请参考以下内容:
let view = View()
let controller = ConcreteController()
view.setDelegateController(controller)
view.test() // This will print:
// Controller
// Delegate
testGeneric
的函数体中,你可以声明一个 T
类型的变量。 - 0x416e746f6etestGeneric
函数,我能否声明一个类型为T:UIViewController,其中T:P1
的变量? - user1046037func
格式已更改,现在看起来像这样:func setup<T: Controller>(viewController: T) where T: Delegate
。 - xaphodUIViewController
约束到该协议中,然后使用protocol<>
指令将两个协议组合成一个单一的类型:protocol UIViewControllerType {} // empty
protocol P1 { ... }
// Make sure only UIViewController adopts UIViewControllerType
extension UIViewController: UIViewControllerType {}
extension UITableViewController: P1 {}
// This works:
var v1: protocol<UIViewControllerType, P1> = UITableViewController()
// This doesn't:
var v2: protocol<UIViewControllerType, P1> = UIViewController()
v1
(不转换类型)调用UIViewController
方法。我主要是想要这个来进行委托。 - user1046037UIViewController
方法添加到 UIViewControllerType
协议中。但我同意这不太美观。 - Ole Begemannprotocol P1 {
func f1()
func getVC() -> UIViewController
}
class MyVC : UIViewController, P1 {
func f1() {
// do stuff
}
func getVC() -> UIViewController {
return self
}
}
var v1 : P1 = MyVC()
v1.getVC() // do UIViewController related things