簡體   English   中英

在Swift屬性中需要協議和類

[英]Requiring Protocol and Class in Swift Properties

在Objective-C中,您可以要求屬性的類和其他協議實現:

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

這在Swift中可能嗎? 從文檔中看起來你只需要一個類或一個協議。

實際上有兩種方法可以在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? } 

我希望下一個Swift版本添加一種方法來指定兩個約束而不使用“幻像協議”......

typealias ViewControllerType = UIViewController: UISplitViewControllerDelegate // wish

是的,你可以這樣做

class A < T : SomeClass where T: Comparable> {
    var myProperty: T
    init(t :T) {
        myProperty = t
    }
}

聲明類A具有類型T的屬性T是SomeClass或亞類的,它有采用Comparable協議

聲明屬性時,可以使用protocol作為類型

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> 
}

你可以在這里閱讀文檔

與@akashivskyy回答相同,使用空的“幻影”協議
但在這里,我將它作為單獨的類來實現該協議 - 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.
    }
}

在Swift 4中,你可以通過以下方式實現:

let viewController: UIViewController & UISplitViewDelegate

這是需要泛型的地方。

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

假設你想要一個名為'MyClass'的類有一個名為'viewController'的屬性,其類型為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類型,但您還指定希望從UIViewController派生T並符合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.
    }

    //..
}

更多信息在這里

祝好於仿制葯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM