简体   繁体   English

协议扩展中的快速关闭

[英]Swift closure in protocol extension

I want to Decorate UIViewController with the ability to adjust it's interface when setInteractionEnabled method is called from another class (ex. Network State Manager). 当从另一个类(例如,网络状态管理器)调用setInteractionEnabled方法时,我想装饰UIViewController并具有调整其界面的功能。 All changes (if any) should be provided in the concrete controller by overriding onInteractionChanged . 所有更改(如果有的话)都应通过重写onInteractionChanged在具体控制器中提供。 Here is my code: 这是我的代码:

import Foundation

typealias InteractionClosure = ((enabled: Bool) -> Void)

protocol Interaction: class {

    var onInteractionChanged: InteractionClosure? { get set }

    func setInteractionEnabled(enabled: Bool)

}

extension Interaction where Self: UIViewController {

    // Default: Do nothing
    // Throws: - Extensions may not contain stored properties
    var onInteractionChanged: InteractionClosure? = nil

    func setInteractionEnabled(enabled: Bool) {
        onInteractionChanged?(enabled: enabled)
    }

}

extension UIViewController : Interaction {}

How to add default implementation for onInteractionChanged ? 如何为onInteractionChanged添加默认实现?

Answering my own question is something usually I don't do, but here is my solution: 我通常不会回答我自己的问题,但这是我的解决方案:

typealias InteractionClosure = (enabled: Bool) -> Void

protocol Interaction: class {

    func addOnInteractionChanged(closure: InteractionClosure)
    func setInteractionEnabled(enabled: Bool)

}

extension Interaction where Self: UIViewController {

    func addOnInteractionChanged(closure: InteractionClosure) {
        onInteractionChanged = closure
    }

    func setInteractionEnabled(enabled: Bool) {
        onInteractionChanged?(enabled: enabled)
    }

    // MARK: - Private

    private var onInteractionChanged: InteractionClosure? {
        get {
            let wrapper =
                objc_getAssociatedObject(self, &icAssociationKey) as? ClosureWrapper
            return wrapper?.closure
        }
        set(newValue) {
            objc_setAssociatedObject(self,
                                     &icAssociationKey,
                                     ClosureWrapper(newValue),
                                     .OBJC_ASSOCIATION_RETAIN)
        }
    }

}

extension UIViewController : Interaction {}

// Helpers

private var icAssociationKey: UInt8 = 0

private class ClosureWrapper {
    var closure: InteractionClosure?

    init(_ closure: InteractionClosure?) {
        self.closure = closure
    }
}

Client class: 客户类别:

class LoginViewController: UIViewController {

    // MARK: - Lifecycle

    override func viewDidLoad() {
        super.viewDidLoad()
        self.setup()
    }

    // MARK: - Private

    private func setup() {
        // ...

        addOnInteractionChanged { [unowned self] (enabled) in            
            self.signInButton.enabled = enabled
            self.activityIndicatorView.hidden = !enabled
        }
    }

}

In manager class: 在经理班:

visibleViewController?.setInteractionEnabled(true)

If you would like property to have only { get } ability, you can use: 如果您希望属性仅具有{ get }能力,则可以使用:

protocol TestProtocol {
    var testClosure: ((_ parameter: Bool) -> Void)? { get }
}

extension TestProtocol {
    var testClosure: ((_ parameter: Bool) -> Void)? {
        return { parameter in
            print(parameter)
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM