簡體   English   中英

Swift 協議屬性與代表

[英]Swift protocol properties with delegates

我正在嘗試通過協議和擴展在 controller 上設置成功/錯誤視圖。

我想要實現的是,我想進入 state,它足以在 controller 上實現協議,並從那里訪問 successView(沒有額外的樣板)。

這是我到目前為止所擁有的:

protocol SucessViewProtocol where Self: UIViewController {
    
    func initSuccessView()

    var successView: UIView! { get set }
    var topConstraint: NSLayoutConstraint! { set get }

    func showSuccess()
    func hideSucess()
}

extension SucessViewProtocol {

    func showSuccess() {
        //animate displaying success message
    }

    func hideSucess() {
        //animate hiding success message
    }

    func initSuccessView()  {
        successView = UIView()
        topConstraint = NSLayoutConstraint()
        // init success view and top constraint
    }
}

現在,當我在 controller 上實現協議時,它看起來像這樣:

// MARK: SuccessView
extension ConsumingViewController: SucessViewProtocol {
    var successView: UIView! {
        get {
            //getter
        }
        set {
            //setter
        }
    }

    var topConstraint: NSLayoutConstraint! {
        get {
            //getter
        }
        set {
            //setter
        }
    }
 
}

我想我的問題很明顯,因為我在實現 SucessViewProtocol 的 controller 中獲得了 successView 和 topConstraint 作為屬性。 我正在從擴展中的協議初始化屬性,所以我需要的只是訪問這些屬性(而不是在我的控制器中再次聲明它們)。 我想我在協議 - 擴展 - controller 之間遺漏了一些“膠水”部分

我希望能夠在 controller 上實現該協議,調用initSuccessView()並從那里調用showSuccesshideSuccess就足夠了。

編輯:

這就是我想使用這個結構的方式:

class ConsumingViewController: UIViewController {
   func viewDidLoad() {
     initSuccessView()
     
     loadData()
   }

   private func loadData() {
     //successfullyloaded
     showSuccess()
   }

}

// MARK: SuccessView
extension ConsumingViewController: SucessViewProtocol {
  var successView: UIView! {
    get {
        //getter
    }
    set {
        //setter
    }
  } *PROBLEMATIC*

  var topConstraint: NSLayoutConstraint! {
    get {
        //getter
    }
    set {
        //setter
    }
  } *PROBLEMATIC*

}

正如我所說,問題在於屬性 successView 和 topConstraing 在 ConsumingViewController 中被重新聲明(因為它們是協議的一部分)。 我需要在 controller 中實際上不可見,而只是在擴展中使用。 但是擴展中的存儲屬性存在問題......

可能是你想要的嗎?

protocol SucessViewProtocol {
    func showSuccess()
    func hideSucess()
}

fileprivate struct Key {
    static var runtimeKey: Int = 0
}

extension SucessViewProtocol where Self: UIViewController  {
    var successView: UIView? {
        get {
            return objc_getAssociatedObject(self, &Key.runtimeKey) as? UIView
        }
        set {
            objc_setAssociatedObject(self, &Key.runtimeKey, newValue, .OBJC_ASSOCIATION_RETAIN)
        }
    }

    func showSuccess() {
        successView = UIView()
        //animate displaying success message
        view.addSubview(successView)
    }

    func hideSucess() {
        //animate hiding success message
        successView?.removeFromSuperview()
    }
}

像這樣在主 scope 中添加協議變量而不是擴展 scope UIViewController。

public class ViewController: UIViewController, SucessViewProtocol {
    var successView: UIView!
    var topConstraint: NSLayoutConstraint!    
}

通過這樣做,您不需要為屬性定義 getter 和 setter

在 ViewDidLoaded 中,您可以初始化SuccessView:

public override func viewDidLoad() {
        super.viewDidLoad()
        
        self.initSuccessView()
    }

並調用自定義 function:

func show() {
        self.showSuccess()
    }
    
    func hide() {
        self.hideSucess()
    }

解決方案 = 可選協議

您只需要向擴展添加屬性,並使它們成為可選的。

protocol SucessViewProtocol where Self: UIViewController {

    func initSuccessView()

    var successView: UIView! { get set }
    var topConstraint: NSLayoutConstraint! { set get }

    func showSuccess()
    func hideSucess()
}

extension SucessViewProtocol {

    // 👇🏼------ these 2 properties added ------👇🏼
    var successView: UIView! { get{ nil } set{} }
    var topConstraint: NSLayoutConstraint! { get{ nil } set{} }

    func showSuccess() {}

    func hideSucess() {}

    func initSuccessView()  {
        successView = UIView()
        topConstraint = NSLayoutConstraint()
    }
}

然后,當您在ConsumingViewController上遵循SucessViewProtocol時,您將不需要實現屬性。

// MARK: SuccessView
extension ConsumingViewController: SucessViewProtocol {
    // There's NO compiler error here!
}

暫無
暫無

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

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