There is a little problem with UINavigationBar which I\'m trying to overcome. When you hide the status bar using prefersStatusBarHidden() method in
Objective-C, which uses dynamic dispatch supports the following:
Class method swizzling:
The kind you're using above. All instances of a class will have their method replaced with the new implementation. The new implementation can optionally wrap the old.
Isa-pointer swizzling:
An instance of a class is set to a new run-time generated sub-class. This instance's methods will be replaced with a new method, which can optionally wrap the existing method.
Message forwarding:
A class acts as a proxy to another class, by performing some work, before forwarding the message to another handler.
These are all variations on the powerful intercept pattern, which many of Cocoa's best features rely on.
Enter Swift:
Swift continues the tradition of ARC, in that the compiler will do powerful optimizations on your behalf. It will attempt to inline your methods or use static dispatch or vtable dispatch. While faster, these all prevent method interception (in the absence of a virtual machine). However you can indicate to Swift that you'd like dynamic binding (and therefore method interception) by complying with the following:
public dynamic func foobar() -> AnyObjectIn the example you provide above, these requirements are being met. Your class is derived transitively from NSObject via UIView and UIResponder, however there is something odd about that category:
Try instead to move the Swizzling code into your AppDelegate's did finish launching:
//Put this instead in AppDelegate
method_exchangeImplementations(
class_getInstanceMethod(UINavigationBar.self, "sizeThatFits:"),
class_getInstanceMethod(UINavigationBar.self, "sizeThatFits_FixedHeightWhenStatusBarHidden:"))