How to restore status bar correctly? - visibility

I am making an app that requires the status bar to be hidden on one screen, but I then want it to come back on when the user goes back to the previous screen. I am using [[UIApplication sharedApplication] setStatusBarHidden:NO];, which works, but when I turn it on, it overlaps the navigation bar and slows the app down to the point that it crashes. Is there anything else I can use, or am I just not using the code correctly?

I had what would seem to be a similar problem in moving from a DetailView to a FlipView - in which I wanted to have the status bar hidden to show a photo against a black background - and then back to the DetailView. The key thing seemed to be to have the code to revert the hiding in the viewWillDisappearAnimated method of the FlipView, rather than in its ViewDidUnload method or in a method in the DetailView controller. I suppose this resets everything before you return to your previous view. So my code in my FlipViewController was:
- (void)viewDidLoad
{
[[UIApplication sharedApplication] setStatusBarHidden:YES];
// other application-specific code
}
and
- (void)viewWillDisappear:(BOOL)animated
{
[[UIApplication sharedApplication] setStatusBarHidden:NO];
}
Hope this helps.

Related

ViewController canBecomeFirstResponder iOS 8

I have a VC that has an inputAccessoryView that is used to display a textfield (much like the messages app). When I push this view onto the navigation stack everything works fine and by that I mean that the tableview adjusts its insets to make sure nothing scrolls underneath that accessory view. However, if from that view I push on another instance of the same view controller class the insets will not be adjusted and the scrolling of the table will be behind the accessory view.
This issue is seen in iOS 8 only. The other interesting thing about this is that if you then click in the accessory view to open the keyboard the insets are adjusted properly for the keyboard being visible and again when it's hidden.
Also if you don't click the text field to fix the issue and hit back the previous VC is broken as well.
I'm fairly certain based on the information above that this is an iOS 8 bug. I'm hoping someone has seen this and come up with semi reasonable fix.
Nasty solution but a solution nonetheless:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self.inputAccessoryView.inputAccessoryTextField becomeFirstResponder];
[self.inputAccessoryView.inputAccessoryTextField resignFirstResponder];
});
}
This allows the view to redraw the insets

Hide time and battery status

I have a Navigation Controller with nav bar. The issue I have is I can set the status bar to white, but once the nav bar animates onto the page, they return to black. I've tried using the following with no success:
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
[UIApplication sharedApplication.setStatusBarStyle = UIStatusBarStyleLightContent;
-(UIStatusBarStyle)preferredStatusBarStyle {
return UIStatusBarStyleLightContent;
}
and still the time, batter status, etc return to black. I would be fine with making it completely disappear if no one can figure out what I'm doing wrong lol. Thanks in advance.
Starting with iOS 8 the status bar gets its color from the view controller of the top most view that is currently visible. Try setting the following on the Navigation Controller (assuming the UINavigationController view is the top most view):
<navController>.navigationBar.barStyle = UIBarStyleBlack;
If that doesn't work try adding the override to the top level UIViewController as you did (make sure its the primary view controller contained in your UIWindow.. assuming this is not your UINavigationController..]):
-(UIStatusBarStyle) preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
Also:
In the .plist file for your project, make sure the "View controller-based status bar appearance" is set to YES.
Alternative
If you want your
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
command to have an effect set "View controller-based status bar appearance" to NO in your .plist file. Please note though that view controller based status bars are the wave of the future and some third party libraries (like PSPDFKit) now require this option to be enabled.
Hiding Status Bar
If you want to hide the status bar you can try by setting "View controller-based status bar appearance" to NO in your .plist file. Then add the following code to viewWillAppear of your main view controller:
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];

Why is the NSStatusItem displaying multiple times?

A NSStatusItem has a NSMenu attached, and one of the buttons of the NSMenu opens a NSWindow. Whenever one of these buttons is clicked, the window opens as expected and works properly, but another display of the NSStatusItem is opened.
The NSStatusItem is a clock, so I can see that it is updating correctly. However, the cloned NSStatusItem doesn't have its own menu. If I push the button that makes the window more times, more cloned versions of the NSStatusItem pop up.
Everything works fine except for this.
That's not a whole lot of information to go off of, but there's nothing else I can think of that could potentially help you. I would be happy to provide more information or try something.
EDIT: Every time the button is clicked, awakeFromNib is somehow called, which is why another half-working NSStatusItem happens.
EDIT: Temporary workaround is to put the awakeFromNib method in a dispatch_once.
EDIT: Added method that is triggered when button is clicked, as suggested by #zpasternack
- (IBAction)preferences:(id)sender {
self.windowController = [[NSWindowController alloc] initWithWindowNibName:#"PreferencesWindow"];
[[self windowController] showWindow:self];
}
Is the NSStatusItem contained in the PreferencesWindow nib? That might explain it, since you're loading the nib each time the button is clicked.
Also, is there a reason you need to recreate that window each time the button is clicked? Maybe you could only do it the first time?
- (IBAction)preferences:(id)sender {
if( self.windowController == nil ) {
self.windowController = [[NSWindowController alloc] initWithWindowNibName:#"PreferencesWindow"];
}
[[self windowController] showWindow:self];
}

Cocoa ignore clicks but still register them?

Is it possible to have a click-through window in cocoa (as in _window.ignoreMouseEvents = TRUE), but still find out when the mouse has been clicked above the window? Or, instead of ignoring the events, registering them, and then somehow forwarding them, propagating them to whatever is behind the window?
I guess what you are looking for is the NSView method hitTest.
This method is called on every view when a mouse click is received.
- (NSView*)hitTest:(NSPoint)aPoint
{
return self;
}
Returning self would mean that the click is not forwarded to the next subviews.
Returning [super hitTest] would just forward the click to the parent view of your view hierarchy. Using this, you could simply register clicks without anything else happening.
So something like:
- (NSView*)hitTest:(NSPoint)aPoint
{
[self propagateEventToNextApplication];
return [super hitTest:aPoint];
}
Hope this helps!

How to use NSTrackingArea

I'm new to Mac programming and I want to fire events when the cursor enters or exits the main window. I read something about NSTrackingArea but I don't understand exactly what to do.
Apple provides documentation and examples for NSTrackingAreas.
The easiest way to track when a mouse enters or exits a window is by setting a tracking area in the window's contentView. This will however not track the window's toolbar
Just as a quick example, in the custom content view's code:
- (void) viewWillMoveToWindow:(NSWindow *)newWindow {
// Setup a new tracking area when the view is added to the window.
NSTrackingArea* trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] options: (NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways) owner:self userInfo:nil];
[self addTrackingArea:trackingArea];
}
- (void) mouseEntered:(NSEvent*)theEvent {
// Mouse entered tracking area.
}
- (void) mouseExited:(NSEvent*)theEvent {
// Mouse exited tracking area.
}
You should also implement NSView's updateTrackingAreas method and test the event's tracking area to make sure it is the right one.
Answer by Matt Bierner really helped me out; needing to implement -viewWillMoveToWindow: method.
I would also add that you will also need to implement this if you want to handle tracking areas when the view is resized:
- (void)updateTrackingAreas
{
// remove out-of-date tracking areas and add recomputed ones..
}
in the custom sub-class, to handle the view's changing geometry; this'll be invoked for you automatically.

Resources