我正在尝试开发一个主题引擎,它从json
加载主题。我有Thememanager
这是singleton
类,并且拥有currentTheme
变量。
然后我有baseViewController
在currentTheme
技术的帮助下监听Boxing
中的任何更改,并且所有viewControllers都需要是子类的
base
需要override
observer
方法来应用他们的样式。在box
类中,我有一个listeners
数组,以便多个视图控制器可以同时观察主题更改,它运行良好,现在
我的问题是,每当一个视图控制器获得deallocated
时,我想从侦听器的盒子类数组中删除该侦听器,我无法弄清楚,因为哪些侦听器被堆积起来。
我尝试在viewController的deint中编写一个unbind
方法,并试图像下面那样传递闭包,但它没有工作
func unbind(listener: Listener?) {
self.listeners = self.listeners.filter { $0 as AnyObject !== listener as AnyObject }
}
Thememanager
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)
}
}
BOX
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 }
}
}
BaseViewController
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
}
答案 0 :(得分:0)
问题在于unbind
方法中闭包的比较,因为它可用于闭包和函数()。见this。我猜你可以维护一个hashmap,其中侦听器是值,唯一标识符是键。解除绑定也会快得多。
但是,我觉得Notifications的方式要好得多,因为它可以为您提供相同的行为(Publisher-Subscriber),而无需管理听众。