Background
As far as why you see this discrepancy in notifications firing, it probably has to do with how KVO works. You observe the value of a property. In this case, statusBarHidden
. But, in order to get notifications, that property must have been changed by way of the setter that exists for it.
Notifications can't happen magically, so it effectively needs to be coded as a side-effect of the setter. (this is often done for you automatically, when coding your properties) However, the class that has that property could also choose to modify an ivar directly. In this case, UIApplication
has/had an internal struct _applicationFlags
, which contains
unsigned int statusBarHidden:1;
So, it's entirely possible that setStatusBarHidden:withAnimation:
is just modifying the underlying data member directly, which bypasses the setter needed to callback your observer.
Solution?
In terms of workarounds for you, you don't mention whether this app is for the app store or not (could be for personal/hobby purposes, could be an Enterprise app, or could be a jailbreak app).
One thing that might be an option for you is to use method swizzling to replace the default implementation of setStatusBarHidden:withAnimation:
with one of your own. Your own implementation could simply call setStatusBarHidden:
, which would then re-enable KVO. Or, if you wanted to keep the animation, you could probably use GCD to schedule setStatusBarHidden:
to run after the amount of time it takes setStatusBarHidden:withAnimation:
to finish animating. That way, you'd still get the animation, and also have the KVO triggered by calling setStatusBarHidden:
.
It's not clear to me whether method swizzling is always rejected in App Store apps. I thought it was (at least, when swizzling methods in iOS frameworks), but according to this, it is either allowed, or can slip through.
The next question would be, "if method swizzling really is something Apple wants you to avoid, despite it being in public APIs, is there a way to work around that?"
Unless the people in the Stack Overflow question I linked to were lying, it looks like it does get through review (at least sometimes). So, maybe it's not tested for in an automated way. Maybe it's sometimes visually recognized by human testers, who see a standard feature working differently, in a way that they deduce must be a result of method swizzling. In this case, you don't actually want to use it to change the status bar UI behavior, just to latch on to a notification, so that shouldn't bother them.
Or, they might be searching for selectors for known iOS APIs (used with swizzling). If that's the case, selectors built from strings can pretty easily be obfuscated, to avoid detection.
Anyway, just some options ...