2017-04-18 26 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) 
     } 
    } 

也许这不是一个很优雅的方式,希望有人能纠正错误。