[英]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.