2017-04-18 6 views
4

クラスとプロトコルについて非常に多くの記事を読んだことがありますが、まだ解決策が見つかりませんでした。私はちょうどそれらのすべてを理解していないかもしれません。Swift 3、プロトコルに準拠したクラスのオブジェクトを返すプロトコルで機能する

だから、単純なプロトコル(問題に関係のないいくつかの部分を削除)です:

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

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

は、しかし、私はタイプUIViewController?のオブジェクトを返しますが、それは、プロトコルに準拠している必要がありませんのみ機能viewControllerForItemIndexをしたいと思います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) 
     } 
    } 

それは非常にエレガントな方法ではないかもしれない、誰かが間違いを訂正できることを願っています。

関連する問題