Swift 3,在协议中起作用,返回符合协议的类对象

时间:2017-04-18 18:59:45

标签: swift

我已经阅读了很多关于课程和协议的文章,但仍然没有找到解决方案。可能我只是不了解所有这些。

所以有一个简单的协议(删除了一些与问题无关的部分):

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

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

但我希望函数viewControllerForItemIndex不仅返回类型为UIViewController?的对象,而且还应符合协议InfoObjectDisplaying(此处未显示)。

在Objective-C中我会写:

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

这可以在swift中实现吗?

2 个答案:

答案 0 :(得分:3)

首先,您不需要在Swift中继承NSObjectProtocol:)

不,你不能直接在Swift中这样做。您可以要求对象符合协议或类,但不能同时符合两者。但是,您可以viewControllerForItemIndex声明为通用函数,并要求其类型参数符合特定要求:

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

答案 1 :(得分: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)
        }
    }

也许这不是一种非常优雅的方式,希望有人可以纠正这些错误。