Dani
Dani

Reputation: 3637

Protocol not being executed

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

Answers (1)

Miknash
Miknash

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

Related Questions