2017-04-18 25 views
4

我已經閱讀了許多關於類和協議的文章,但仍未找到解決方案。可能我只是不明白所有這些。Swift 3,在返回符合協議的類的對象的協議中的功能

所以這是一個簡單的協議(去掉了一些的問題不相關部分):

protocol InfoObject : NSObjectProtocol 
{ 
    var statusImage: UIImage? {get} 

    func viewControllerForItemIndex(_ index: Int?) -> UIViewController? 
} 

但我想功能viewControllerForItemIndex不僅返回UIViewController?類型的對象,但應符合協議InfoObjectDisplaying (這裏沒有顯示)。

在Objective-C我會寫:

- (UIViewController<InfoObjectDisplaying>*)viewControllerForItemIndex:(NSInteger) index; 

這是可能的迅速?

+1

目前不是 - 但[在未來版本的語言中可能](https://github.com/apple/swift-evolution/blob/master/proposals/0156-subclass-existentials.md)。 – Hamish

回答

3

首先,你不需要從NSObjectProtocol斯威夫特繼承:)

不,你不能這樣直接在斯威夫特做。您可以要求對象符合協議或類,但不能同時使用兩者。但是,您可以聲明viewControllerForItemIndex作爲一種通用的功能,並要求其類型參數符合具體要求:

func viewControllerForItemIndex<T: UIViewController where T: InfoObjectDisplaying>(_ index: Int?) -> T? 
+0

感謝您的回答。我已經閱讀過有關使用泛型,但我希望有一個「真正的」解決方案。 :-) –

+0

現在不幸的是,據我所知,還沒有。 :/ –

+0

不知道如果語法更新在Swift 3.1,但我只是讓Xcode糾正這個'func viewControllerForItemIndex (_ index:Int?) - > T?其中T:InfoObjectDisplaying' –

0

我解決這個問題是這樣的:

protocol ScanningMessageViewProtocol: class { 
    func showMessage(_ message: String, animated: Bool) 
    func showMessage(_ message: String, autoHideAfterDelay time: TimeInterval?, animated: Bool) 
    func hideMessage(animated: Bool) 
} 
extension ScanningMessageViewProtocol where Self: UIView {} 

protocol CLScanBarcodeViewControllerDelegate: class { 
    func messageViewForScanController(_ controller: CLScanBarcodeViewController) -> ScanningMessageViewProtocol 
} 
extension CLScanBarcodeViewControllerDelegate where Self: UIViewController { 
    func messageViewForScanController(_ controller: CLScanBarcodeViewController?) -> ScanningMessageViewProtocol? { return nil } 

}

使用它是這樣的:

if let messageView = self.delegate?.messageViewForScanController(self) { 
     if messageView is UIView { 
      self.view.addSubview(messageView as! UIView) 
      (messageView as! UIView).translatesAutoresizingMaskIntoConstraints = false 
      let size: CGSize = self.view.bounds.size 
      let cropSize: CGSize = CGSize(width: size.width * 0.7, height: size.width * 0.7) 
      let cropRect = CGRect(x: (size.width - cropSize.width)/2.0, 
            y: (size.height - cropSize.height)/2.0 - distanceToCenterY, 
            width: cropSize.width, 
            height: cropSize.height) 
      self.view.addConstraint(NSLayoutConstraint(item: messageView, attribute: .leading, relatedBy: .equal, toItem: self.view, attribute: .leading, multiplier: 1, constant: 20)) 
      self.view.addConstraint(NSLayoutConstraint(item: messageView, attribute: .trailing, relatedBy: .equal, toItem: self.view, attribute: .trailing, multiplier: 1, constant: -20)) 
      self.view.addConstraint(NSLayoutConstraint(item: messageView, attribute: .top, relatedBy: .equal, toItem: self.view, attribute: .top, multiplier: 1, constant: cropRect.minY + cropRect.height + 30)) 
      self.view.addConstraint(NSLayoutConstraint(item: messageView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 0, constant: 30)) 
      messageView.showMessage("this is message", animated: true) 
     } 
    } 

也許這不是一個很優雅的方式,希望有人能糾正錯誤。