Setting background views depending on user settings - iphone

I've got an app where the background needs to be set depending on user preference. The user can change this at any time via settings tab. I've got it working by checking NSUserDefaults in viewWillAppear and setting self.view.backgroundColor. This is really clunky.
The right approach (I thought) is to set the background in the root view and for every views that gets on the stack inherit the background. So in viewDidLoad, I've got
self.view.backgroundColor = [UIColor clearColor];
I would have thought this should work. But all I get is a clear background. Any guidance is greatly appreciated.

Your first approach was right. Pushed views don't "go over" the root view--old views are pushed off the screen (and can be released if there is a memory warning). You have to set the background color in each view. If you want to avoid redundancy, you can make an abstract superclass that sets the background color.

Views are layered.
So if there are views "on top of" the root view and you want to "see" the root view's background color, make sure any views on top are transparent (i.e. Opaque is off, and/or the background alpha is 0.0).

Related

Why am I getting a blank slate after the iOS loading screen?

My app is displaying the correct iOS loading screen, and then a white screen.
Is it incumbent on me to overwrite the white screen appropriately? Before I added loading screens, I had a background view loaded, and images on top of it. Now it just is plain white.
For displaying the background correctly, does it make sense to have a draw screen method, called from viewDidLoad and from viewDidRotate, and tackle things from there?
I have a ContainerView under a ScrollView, and the ScrollView is provisionally 150x150, which should even if it clips things show non-white pixels inside.
What should I do to get real diagnostics?
My app is displaying the correct iOS loading screen, and then a white screen.
Something is wrong with your initial view controller, or with the view that it's supposed to load.
Is it incumbent on me to overwrite the white screen appropriately?
The white screen is probably either your app's window or an empty view. Normally, your app delegate would create a root view controller and load its view into the app's window (possibly automatically if you're using storyboards). It sounds like something happened to adversely affect that process -- your storyboard was changed, your Info.plist (which points the app to the right storyboard or .xib file) was changed, etc.
For displaying the background correctly, does it make sense to have a
draw screen method, called from viewDidLoad and from viewDidRotate,
and tackle things from there?
That shouldn't be necessary, at least in the context of your current problem.
What should I do to get real diagnostics?
Use the debugger. Is the window's root view controller pointing to an instance of the correct class? If yes, does its view property point to the correct view? If yes, does the view contain the appropriate objects?

MKMapview Affecting UINavigationBar and TabBar Appearance

I have a MKMapView in a UIView. Never any issues until iOS7. My colors for UITabbar and UINavigationBars are set by UIAppearance Protocol.
For some reason whenever the MKMapView is initiated, all my tabbars and navbars reset, ignoring the barTintColor setting of my appearance class. All other settings from UIAppearance seem to remain such as title attributes and barItem attributes. Only barTintColor goes out.
One more thing. This only happens on iPhone 4 and iPhone4S, not on iPhone 5. It does not happen on the simulator either. Was not an issue in iOS6 at all.
I can find no other cause for the reset. I went through and commented out just about all the goings on and it had no effect either way.
If I delete the MKMapView control, no reset of colors. If I then go on to present another, altogether different view with an MKMapView, again the colors reset.
I am looking for ideas of what else to check, what kind of settings or methods could possibly cause this behavior. Give me some stuff to eliminate, I am stuck.
Additional Info:
Now thinking this may be a bug. I put a line to hard code the color of the navbar to an arbitrary color in ViewDidLoad just to see what is going on.
UINavigationBar *bar = self.navigationController.navigationBar;
[bar setBarTintColor = [UIColor GreenColor];
I put a break on the next line. Inspecting bar, the color seems to be set.
On iPhone4 or 4S, bar does not turn green. On iPhone5 and simulator, bar turns green.
Some more items I have discovered. The color is not changing. It appears the visibility is. Yet, reading the alpha of the color and of the bar returns 1.0 both.
So color is correct.
Translucency is yes.
Alpha is 1.0.
And yet the bar is completely clear, no color, no tint.
I think I will file this officially as a bug. I made a test viewController with only a MKMapview. No code, no delegate, no annotations. Presented that in place of my proper controller. The same thing happened.
What I need right now is a workaround. I just cannot tell what is changing. When I inspect the properties of the navigation bar, everything is correct. Tint color, translucency, bar Tint Color, alpha value. So far as I can tell, the thing should be displaying as intended.
Can anyone tell me other properties or methods that could make the background of the navigation bar completely transparent?
After some more searching I see that there are some related threads in the developer forums and this issue has been noted for some time. I expect I will receive response that my bug report is a dupe. In the meantime, I believe I have come up with a workaround.
What I came up with is a sequence of setting
self.navigationController.navigationBar.translucent = NO;
self.tabBarController.tabBar.translucent = NO;
when the view containing a MKMapView is loaded and then setting it YES in viewDidAppear. I set to NO again on viewWillDisappear. Then the returning viewController must reset to translucent again in its viewDidAppear.
I used a series of NSNotification posts in the View Controllers with the maps. I subclassed my navigation controllers and tab bar to make them listen for the notification and respond by toggling their own bar translucency property.
Managed to get it done. With a small amount of code, but it is an awful lot of activity for no good reason. Would more like to see this fixed ASAP.

Why is there a 20-pixel-high dark overlay over my app's navigation bar?

Once again, I'm almost entirely sure this is something dumb that I'm doing, but I've been banging my head against this one for hours & am getting nowhere.
I'm trying to restructure the view hierarchy of my app. I need to be able to detect user interface orientation changes globally in order to correctly rotate a "Loading" view displayed when the app is downloading content. (device orientation changes seem to fire at different times, causing the view that needs to respond to these events to rotate sporadically).
The app previously added a UINavigationController's view to the main window. I modified the hierarchy to add the view of a UIViewController subclass to the main window, and added the view of the UINavigationController to the subclass's view. The UIViewController subclass manages the display & rotation of the "Loading" subview, and I was expecting the rest of the app to continue behaving normally, as inserting one extra empty view into the hierarchy didn't feel like I was changing too much.
My initial problem was the positioning of the UINavigationController - it was 20 pixels too low, resulting in a gap between the status bar and the navigation bar, and cutting off the bottom 20 pixels of the tab bar. I was able to adjust this by setting the frame property of the UINavigationController's view to the bounds property of the UIViewController's view, which corrected the position.
However, now I'm stuck with a 20-pixel-high dark "overlay" on top of my navigation bar. If I were to guess, I'd say it was black with 50% opacity. Touch events on this bar don't work (e.g. if I try to tap the "Back" button through the overlay, nothing happens). The fact that the height is equal to that of the status bar hasn't escaped me, but I'm at a total loss as to what could be causing it.
I hate feeling this stupid, so if anyone has any insight into this problem, you'd really make my day. Thanks in advance!
OK, a few things pop out from your post.
My initial problem was the positioning of the
UINavigationController - it was 20
pixels too low
This makes me believe it is related to your new problem.
I was able to adjust this by setting
the frame property of the
UINavigationController's view to the
bounds property of the
UIViewController's view
This sounds like the view it was loaded onto was offset 20 pixels, and when you set it to the bounds, it repositioned it on the windows view space.
Touch events on this bar don't work
(e.g. if I try to tap the "Back"
button through the overlay, nothing
happens)
This is the big thing. If touch events aren't being sent to the view, then what that means is that the OS doesn't see a view where you are pressing (or rather the view you want it to), so that view doesn't get the message to do something.
From what you have said, I believe your problem is with your base view controller that you just added. Try redoing the frame on, making it conform to where you want. Then take out the code you put in to set the navigation controllers frame. The navigation controller should fit to the view you added too, and once you have that main view where it needs to be (20 pixels higher apparently), then everything should work.

Is it possible to change the frame origins of an iPhone screen as is done when a statusBar is shown or hidden?

When a UIStatusBar is hidden in an app, the origin of all views is (0, 0), the upper left hand corner of the screen. However, when a statusBar is shown, the origin is still (0, 0) yet the views will move down as not to cover the statusBar.
How is this working? Is it possible to duplicate this effect in code?
Essentially, my end goal is to hide the statusBar and replace it with a UIView at certain points in the app (like the google app). But I have a LOT of views and don't want to have to resize all of them after the statusBar is hidden.
You could create a container view enclosing all your "normal" views and set autoresizing masks everywhere. That way, shrinking your container view will automatically resize everything else. In fact, this is how UIViewControllers work. But be aware that while standard Apple controllers like UINavigationController know how to deal with the status bar, they don't know anything about what you want to do, so they're going to be confused more often than not.
Alternatively, you can always show your own status bar underneath the real one, hiding the latter when needed. But in this case you will have to fight Apple-provided controllers which will try to expand when you hide the status bar. You can also play with a two-window layout where the top window does not overlap the status bar, but I'm not sure it will be any easier.
Since Apple doesn't support any of the above, expect a lot of things to stop working correctly. Perhaps, the very best approach is to rethink your UI design.

Annoying white border when rotating a view in iPad

When rotating a View from UIInterfaceOrientationPortrait to UIInterfaceOrientationPortraitUpsideDown on the iPad simulator, there is a white border along one side of the view (see diagram, lower left of the image). The white border shows only on one side, but not the opposite side. How can I prevent (hide) it? Thanks!
This is a guess:
It's possible that one of your views has a backgroundColor set to white, and it is completely covered by another view. During a rotation, perhaps floating point errors cause one border to show slightly through that edge.
To investigate this case, you can use the undocumented method [UIView recursiveDescription] to get a quick look at your view hierarchy (no need to submit code with that method, it's just for debugging). Once you know which views are near the bottom, you can print out their backgroundColors, or just set them all to [UIColor clearColor].
Also, I'm guessing you already know this one, but it can be useful to set window.backgroundColor = [UIColor clearColor] at the start of your code!
I had the same issue. I saw that in Interface builder autosizing for the view could not be enabled. I deleted the .xib and re-created it making sure product was set to "ipad" when creating the file (add new file in xcode).
You can also set the background color to nil. From the UIView documentation for backgroundColor:
The default value is nil, which results in a transparent background
color.
UIWindow inherits from UIView, so this works as well. Probably a good idea to use nil, in case [UIColor clearColor] isn't always the best way to do it.
The funny thing is, I have a project with no nibs, so I create the UIWindow in code, but the background color was white before I set it to nil. is the default background color of a programmatically created UIWindow white?