Method Swizzling to keep a cleaner Class implementation

94 views Asked by At

I'm in the situation where one of the viewControllers of my app is getting pretty big, specially since I've added a "Tutorial state" which adds a different implementation for many methods of this class that I control by checking

_tutorialEnabled?

So, my question is if this is a good use case for method swizzling, I could have this different implementations of these methods in a separate category and swizzle them when required, it might help me reduce the amount of code of the default implementation. Any comments or suggestions of other techniques are appreciated.

3

There are 3 answers

3
Christian Schnorr On BEST ANSWER

No, this is not what method swizzling was designed for.

Personally I would create a subclass of the view controller that manages tutorial related stuff. Then, depending on whether or not the tutorial is enabled, you instantiate either the tutorial controller or its superclass. This is what polymorphism was designed for: to avoid endless if/else/switches.

1
Jeffery Thomas On

Why don't you subclass? Create a tutorial subclass of your view controller with all the needed logic. Present the tutorial in the real view controller's -viewDidAppear: using a full screen modal without animation. When the tutorial is over dismiss the model without animation.

if _tutorialEnabled != nil && _tutorialEnabled {
    tutorialViewController = …
    tutorialViewController.modalPresentationStyle = .FullScreen
    presentViewController(tutorialViewController, animated: NO) {}
}
3
Tristan Burnside On

No, I wouldn't use method swizzling for this. It's a bit like using a sledgehammer to knock in a thumbtack.

Unlike others I also would not subclass a view controller, maintaining understandable flow around view lifecycle events is really important when you want to add other functionality later.

Instead I would use the strategy pattern for this. In your init you could do something like this:

if (tutorialEnabled) {
    self.behaviour = [TutorialBehaviour new];
} else {
    self.behaviour = [NormalBehaviour new];
}

Then when you need to do something that changes you just call a method on your behaviour eg.

- (void)viewDidLoad
{
    ...
    [self.behaviour load]
    ...
}