我正在尝试开发一个主题引擎,它从json
加载主题。 。我有一个Thememanager
这是 singleton
类并持有 currentTheme
多变的。
然后我有一个 baseViewController
它监听 currentTheme
中的任何变化在Boxing
的帮助下技术,并且所有 viewController 都需要是
base
并且需要override
observer
应用他们的风格的方法。在 box
类我有一个数组 listeners
这样多个 View Controller 可以同时观察主题变化,现在效果很好
我的问题是,每当 View Controller 获取 deallocated
,我也想从监听器的框类数组中删除该监听器,但我无法弄清楚,因为监听器正在堆积起来。
我尝试写一个unbind
viewController 的 deint 中的方法并尝试像下面一样传递闭包,但它不起作用
func unbind(listener: Listener?) {
self.listeners = self.listeners.filter { $0 as AnyObject !== listener as AnyObject }
}
主题管理器
class Thememanager {
// Hold a list of themes
var themes = [Theme]()
// Private Init
private init() {
fetchMenuItemsFromJSON()
// You can provide a default theme here.
//change(theme: defaultTheme)
}
// MARK: Shared Instance
private static let _shared = Thememanager()
// MARK: - Accessors
class func shared() -> Thememanager {
return _shared
}
var currentTheme: Box<Theme?> = Box(nil)
func change(theme: Theme) {
currentTheme.value = theme
}
private func fetchMenuItemsFromJSON() {
// TRIAL
let theme = Theme()
themes.append(theme)
}
}
盒子
class Box<T> {
typealias Listener = (T) -> Void
var listeners = [Listener?]()
var value: T {
didSet {
for listener in listeners{
listener?(value)
}
}
}
init(_ value: T) {
self.value = value
}
func bind(listener: Listener?) {
self.listeners.append(listener)
for listener in listeners{
listener?(value)
}
}
func unbind(listener: Listener?) {
self.listeners = self.listeners.filter { $0 as AnyObject !== listener as AnyObject }
}
}
基础 View Controller
class BaseViewController: UIViewController {
private var themeManager = Thememanager.shared()
typealias Listener = (Theme?) -> Void
var currentListener: Listener?
override func viewDidLoad() {
super.viewDidLoad()
observeThemeChange()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// Bind the theme variable so that changes are immediately effective
func observeThemeChange() {
currentListener = {[weak self] (theme) in
guard let currtheme = theme else {
return
}
self?.loadWith(theme: currtheme)
}
themeManager.currentTheme.bind(listener: currentListener)
}
// This method will be implemented by the Child classes
func loadWith(theme: Theme) {
self.navigationController?.navigationBar.tintColor = theme.navigationBarTextColor
self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor : theme.navigationBarTextColor]
// Need to be implemented by child classes
print("theme changed")
}
deinit {
themeManager.currentTheme.unbind(listener: currentListener)
}
}
主题
struct Theme {
// Define all the theme properties you want to control.
var navigationBarBgColor: UIColor = UIColor.darkGray
var navigationBarTextColor: UIColor = UIColor.black
}
最佳答案
问题在于 unbind
方法中闭包的比较,因为它不适用于闭包和 function()。请参阅this 。我想你可以维护一个 HashMap ,其中监听器是值,唯一标识符是键。解除绑定(bind)也会更快。
但是,我觉得通知方式要好得多,因为它为您提供相同的行为(发布者-订阅者),而无需管理监听器。
关于ios - swift:解除监听器的绑定(bind),这些监听器是监听器数组中的闭包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48719228/