在Swift属性中需要协议和类

时间:2014-07-21 06:43:31

标签: swift ios8

在Objective-C中,您可以要求属性的类和其他协议实现:

@property (nonatomic) UIViewController<UISplitViewDelegate> *viewController;

这在Swift中可行吗?从文档中看起来你只需要一个类或一个协议。

5 个答案:

答案 0 :(得分:16)

实际上有两种方法可以在Swift中实现这一目标:

  1. 使用空的“幻像”协议。创建一个空协议并使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?
    }
    
  2. 使用通用约束。正如fnc12Konstantin Koval所述。这是安全的,但不允许您在运行时“交换”视图控制器实例。

    class MyClass<T: UIViewController where T: UISplitViewControllerDelegate> {
        weak var viewController: T?
    }
    

  3. 我希望下一个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

祝好了仿制药。