ios - Swift closure in protocol extension -
i want decorate uiviewcontroller ability adjust it's interface when setinteractionenabled
method called class (ex. network state manager). changes (if any) should provided in concrete controller overriding oninteractionchanged
. here code:
import foundation typealias interactionclosure = ((enabled: bool) -> void) protocol interaction: class { var oninteractionchanged: interactionclosure? { set } func setinteractionenabled(enabled: bool) } extension interaction self: uiviewcontroller { // default: nothing // throws: - extensions may not contain stored properties var oninteractionchanged: interactionclosure? = nil func setinteractionenabled(enabled: bool) { oninteractionchanged?(enabled: enabled) } } extension uiviewcontroller : interaction {}
how add default implementation oninteractionchanged
?
answering own question don't do, here solution:
typealias interactionclosure = (enabled: bool) -> void protocol interaction: class { func addoninteractionchanged(closure: interactionclosure) func setinteractionenabled(enabled: bool) } extension interaction self: uiviewcontroller { func addoninteractionchanged(closure: interactionclosure) { oninteractionchanged = closure } func setinteractionenabled(enabled: bool) { oninteractionchanged?(enabled: enabled) } // mark: - private private var oninteractionchanged: interactionclosure? { { 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)
Comments
Post a Comment