在Objective-C中,您可以要求属性的类和其他协议实现:
@property (nonatomic) UIViewController<UISplitViewDelegate> *viewController;
这在Swift中可行吗?从文档中看起来你只需要一个类或一个协议。
答案 0 :(得分:16)
实际上有两种方法可以在Swift中实现这一目标:
使用空的“幻像”协议。创建一个空协议并使UIViewController
符合它。这是最“Swift”的方法,它是安全的并且是动态的(不需要在编译时指定类)。
protocol _UIViewControllerType {}
extension UIViewController: _UIViewControllerType {}
class MyClass {
weak var viewController: protocol<UISplitViewControllerDelegate, _UIViewControllerType>?
}
你也可以为这种类型声明typealias
(只是为了减少代码混乱)。
class MyClass {
typealias ViewControllerType = protocol<UISplitViewControllerDelegate, _UIViewControllerType>
weak var viewController: ViewControllerType?
}
使用通用约束。正如fnc12和Konstantin Koval所述。这是安全的,但不允许您在运行时“交换”视图控制器实例。
class MyClass<T: UIViewController where T: UISplitViewControllerDelegate> {
weak var viewController: T?
}
我希望下一个Swift版本添加一种方法来指定两个约束而不使用“幻像协议”......
typealias ViewControllerType = UIViewController: UISplitViewControllerDelegate // wish
答案 1 :(得分:4)
是的,你可以那样做
class A < T : SomeClass where T: Comparable> {
var myProperty: T
init(t :T) {
myProperty = t
}
}
声明具有类型T属性的类A
.T是SomeClass
或子类,它必须采用Comparable
协议
声明属性时,可以使用协议作为类型
class MyClass {
var nsobject: NSObjectProtocol
init(object : NSObjectProtocol) {
nsobject = object
}
}
// Pure Swift
protocol RandomNumberGenerator {
}
class Dice {
let generator: RandomNumberGenerator
//specify many protocols
let printer: protocol<Printable, NicePrintable>
}
您可以阅读documentation here
答案 2 :(得分:4)
与@akashivskyy回答相同,使用空“幻影”协议
但在这里,我将它作为单独的类来实现它 protocol - MyViewController,可用作var的类型 宣言。这简化了我的实施。
@objc protocol MySplitViewControllerDelegate : NSObjectProtocol {
func controllerTitle() -> String
optional func mySplitView() // write delegates
}
class MyViewController: UIViewController, MySplitViewControllerDelegate {
func controllerTitle() -> String {
return ""
}
}
class ViewController: UIViewController {
private(set) weak var viewController: MyViewController?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
答案 3 :(得分:3)
在Swift 4中,您可以通过以下方式执行此操作:
let viewController: UIViewController & UISplitViewDelegate
答案 4 :(得分:2)
这是需要仿制药的地方。
@property (nonatomic) UIViewController<UISplitViewDelegate> *viewController;
假设你想要一个名为&#39; MyClass&#34;有一个名为&#39; viewController&#39;使用类型UIViewController(或子类)并符合UISplitViewDelegate协议。在Swift中,您的代码看起来像
class MyClass<T:UIViewController where T:UISplitViewControllerDelegate>:NSObject{
var viewController:T?
override init(){
super.init()
//..
}
// etc..
}
注意
class MyClass<T:UIViewController where T:UISplitViewControllerDelegate>:NSObject
线。在这里,您指定一个随机T类型,但您还指定希望T从UIViewController派生并符合UISplitViewControllerDelegate。编译期间将检查此条件。并在此行声明属性
var viewController:T?
并将其类型指定为T. 还有一个问题 - 如何声明MyClass类型的变量?我提供了一个示例项目中的最小代码,以便更清楚地说明。
class MyClass<T:UIViewController where T:UISplitViewControllerDelegate>:NSObject{
var viewController:T?
override init(){
super.init()
//..
}
// etc..
}
class ViewController: UIViewController,UISplitViewControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var a=MyClass <ViewController> ()
a.viewController=self
//..
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//..
}
更多信息here
祝好了仿制药。