Reputation: 3637
I'm trying to implement light and dark theme throughout the entire app. My problem is that it's not working properly. I have a ContainerVC
that contains 2 ContainerViews
- SidebarMenuVC
and DashboardVC
. SidebarMenuVC
is offset so initially, the user is being displayed DashboardVC
.
The ContainerVC
is embedded in a UINavigationController
and there's a hamburger type menu. When the user taps on that menu button, SidebarMenuVC
is being displayed. It all works just fine.
SidebarMenuVC
contains an image that is responsible for changing the theme of the app. When the user taps on the image it goes from light to dark or vice versa. The moment of tap changes the theme of SidebarMenuVC
but when you hide the menu (via swipe), DashboardVC
's theme is not being applied. I tried to do that with protocol
but I think I'm not doing it correctly (well, its not working so I KNOW i've messed up somehow).
protocol ReloadTheme {
func reload()
}
class ContainerVC: UIViewController, SidebarDelegate {
var delegateReloadTheme: ReloadTheme?
func hideMenu() {
sideBarMenuLeadingConstraint.constant = -300
applyTheme()
animateConstraint()
delegateReloadTheme?.reload() // when I put a breakpoint here, it shows it's nil
}
}
extension DashboardVC : ReloadTheme {
func reload() {
applyTheme()
}
}
So, the big picture is: when the user swipe right to hideMenu()
(which is in ContainerVC
, it somehow needs to access DashboardVC
and call applyTheme()
Protocols/Delegates always confuse me, so a little bit of help is welcome.
Okay, so as requested, here's how the sidebarMenu
is connected:
protocol SideBarDelegate: class {
func showMenu()
func hideMenu()
}
class DashboardVC: UIViewController {
static weak var delegateSideBar: SideBarDelegate?
@IBAction func sideMenuButtonPressed(_ sender: UIBarButtonItem) {
Dashboard.delegateSideBar?.showMenu()
}
}
And then in the ContainerVC
:
class ContainerVC: UIViewController, SideBarDelegate {
override func viewDidLoad() {
super.viewDidLoad()
DashboardVC.delegateSideBar = self
}
func hideMenu() {
sideBarMenuLeadingConstraint.constant = -300
dimView.isHidden = true
applyTheme()
animateConstraint()
// delegateReloadTheme?.reloadTheme()
}
func showMenu() {
sideBarMenuLeadingConstraint.constant = 0
dimView.isHidden = false
applyTheme()
animateConstraint()
}
func animateConstraint() {
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
}
}
And that's how the swipe menu works and it's connected.
Upvotes: 0
Views: 55
Reputation: 7948
You need to assign your delegate somewhere - it is optional type.
For instance, in viewDidLoad
you can say item.delegateReloadTheme = self
.
You need to show more code regarding DashboardVC
.
Basically, when you create delegate, you are creating interface for the work that needs to be delegated, and you delegate it to other class. Because you can implement delegate almost anywhere in the code, you need to tell who is in charge of the implementing that delegate(interface).
for example:
protocol RefresherDelegate {
func refreshUI()
}
Here we define what function(s) will be delegate.
class MyView : UIView {
var delegate: RefresherDelegate?
}
Here, we create variable that will hold object that actually confroms RefresherDelegate
.
class MyObject : RefresherDelegate {
var myView = MyView()
Here you say that MyObject
will implement RefresherDelegate
and create simple MyView instance (won't show on UI, just simple example)
func assignDelegate() {
myView.delegate = self
}
This is crucial part - assign delegate to implementation of it - in this case MyObject
.
After assignDelegate()
, when you actually call refreshUI()
it will be get called in MyObject
.
Upvotes: 1