I'm debugging an iphone app and I'm seeing something I don't understand fully.
Based on user's selection, a UIView is being shown or hidden. Current code shows or hides the view with [view setHidden:NO] and [view setHidden:YES]. This doesn't work: visually it's as if these statements are simply ignored. However when I changed these to view.hidden = NO and view.hidden = YES respectively, everything is working as expected.
I was thinking that the two syntaxes are equivalent, but apparently not. For all other attributes (text, font, etc.), both work identically, so what's so special about hidden?
EDIT: Here's the copy/paste of some of my code. I'm working in XCode 4.3 with iPhone simulator 5.0
Here's one example from my project.
IBOutlet UIView *panel; //Connected in interface builder
===========
- (void)makePanelVisible:(BOOL)visible
{
[panel setHidden:!visible]; //this does not work
panel.hidden = !visible; //this does work correctly.
}
Sets whether the view is hidden.
- (void)setHidden:(BOOL)flag
Returns whether the receiver is marked as hidden.
- (BOOL)isHidden
hidden=YES; is identical to setHidden:YES; The difference is, you are turning hidden to YES right away Whereas sethidden view disappears from its window and does not receive input events because it is set to be hidden. It remains in its superview’s list of subviews, however, and participates in autoresizing as usual.
Thinking back about this, I remember running into the same issue almost 3 years ago, when iPhone 3 (not even 3G) was all the rage. I'm not sure why this happens, but it does - so I just deal with it by setting the property using the "dot" notation. I guess, this is one of those "don't fix it if it ain't broken" things (ok, it is sort of broken, but there's an easy way around it, so I'm using it).
hidden is a property of UIView. When you wrote [panel setHidden:YES], you try to call the method setHidden that should set the property hidden. It doesn't work because the method doesn't exist in the UIView : https://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIView_Class/UIView/UIView.html#//apple_ref/doc/uid/TP40006816
I always set the property by writing "view.hidden = x".
I hope it will help you
Related
I'm having real problems with my apps under iOS8. I've made a bunch of OpenGL based apps, which don't need the iOS to handle the orientation. It's all handled within the OpenGL section. But I do use setStatusBarOrientation to make sure any dialogs/keyboards etc that pop up line up with everything else. I'm creating my window and view programatically or in a xib, I've never needed to use a storyboard (in case thats relevant?)
It's all been perfect, til iOS 8 came along.
Now it seems that setStatusBarOrientation isn't behaving properly at all. It's either not changing anything, or it's rotating "something" that stops touches being recorded on half the screen. It's as if the window is being rotated within itself, but visually nothing changes, just the touches are effected.
It's hard to explain, and makes no sense.
But my question is: How do you set the status bar orientation in iOS8? And how do you do it without destroying everything else that works in previous iOS versions?
Set iOS7.1 as your Base SDK, and it'll work fine on iOS8, without all these strange bugs.
http://objcsharp.wordpress.com/2014/09/21/how-to-get-back-the-ios-7-sdk-after-upgrading-to-xcode-6/
found this
if ([UIViewController class]) // iOS8 has this class only
{
[[UIDevice currentDevice] setValue:[NSNumber numberWithInteger:UIDeviceOrientationPortrait] forKey:#"orientation"];
}
found here:
http://blog.lessfun.com/blog/2014/09/24/ios8-issue-keyboard-orientation-and-idletimerdisabled-not-working/
seems to work
Foreword, this isn't me losing a view off screen because I did the transform wrong, it's weirder.
Problem is, if I use an .m34 transform to achieve the perspective I need, the view hierarchy breaks, but remove the transform and it draws everything correctly.
Here's an example.
I have a background image (subviewOne), a menu(subviewTwo), and an object on top of all of that which I apply the CATransform3D to (subviewThree).
Simple code:
CALayer *layer = subviewThree.layer;
CATransform3D perspectiveTransform = CATransform3DIdentity;
perspectiveTransform.m34 = -1.0 / 500;
layer.transform = perspectiveTransform;
Prior to applying this code, the view hierarchy was, and still is on iOS 5:
(bottom to top)
subviewOne->subviewTwo->subviewThree
After applying it, I end up with:
(bottom to top still)
subviewTwo->subviewOne->subviewThree
Now, subviewThree still has the perspective transform applied to it, and is in the correct spot, on top of everything else, same as on iOS5. However, the Menu/subviewTwo, is now hidden by the background image/subviewOne, and nothing I do will get it to be drawn on top of the subviewOne. No amount of insertSubviewAtIndex:, bringSubviewToFront, sendSubviewToBack, etc, will make the view draw correctly.
This is incredibly peculiar particularly because the views that are drawn out of order are NOT having any kind of CATransform3D applied to them.
I have verified this independently in two different apps and multiple devices 6 devices. iOS5 draws everything correctly, and if I remove those four lines, everything draws correctly, but nothing I've tried on iOS 6 stops the .m34 from breaking the view ordering. It's not always as simplistic as the example I've provided, but this is the most demonstrable case I have witnessed.
Has anyone else experienced this, solved this?
Edit: More info for comment.
Yeah, typo with the extra *.
Figure there's an Imageview, QuadCurve Menu, and Textview.
I was calling the method with the .m34 in the viewDidLoad, but swapped it to the viewDidAppear real quick to check for you.
Doesn't matter. Don't get me wrong, the subviews are listed in the correct order when you call
NSLog(#"%#", [self.view.subviews description]);
They just aren't drawn on screen correctly.
In desperation, I wrote some crazy weird code, and I discovered the following.
I can call the method that draws the menu on a 10 second delay,
[self performSelector:#selector(createQuadCurveMenu) withObject:nil afterDelay:10];
which ends in
[self.view addSubview:menu]
As well as a totally superfluous
[self.view bringSubviewToFront:menu]
and it's still drawn behind an imageView that is set as the lowest subview in the .xib.
I have verified this two ways. I can go into the .xib and set the imageView to hidden, and running again I can see the menu, now that the imageView isn't covering it. I can also just comment out the code that applies the .m34 transform to the textView, and the menu then again correctly appears on top of the imageView. Again, none of this happens on iOS5 and iOS4.
At this point, I'm starting to think that it's a bug inside iOS6 itself, and have been waiting for the NDA to expire so I can ask here if anyone else has experienced it.
Pretty sure this is an iOS 6 bug: I've blogged about it here: iOS 6 Rendering Bug: 3D-Rotation Causes Layers to Render Without Respect for View Hierarchy.
Good news: You can work around the bug by setting zPositions on the affected layers: set the zPositions in increasing order of the view hierarchy. So if I've understood correctly, you want:
subviewOne.layer.zPosition = 0;
subviewTwo.layer.zPosition = 1000;
subviewThree.layer.zPosition = 2000;
Check out the blog for more info, including a link to the Open Radar version of the bug I've logged with Apple.
Also, this might be considered a duplicate of this post: iOS 6 view hierarchy nightmare. It has the same bug source and solution, although the symptoms you both describe are different.
I have a nice little app on the app store that does pretty well for itself. Life was great until iOS 5 came to town. Now, I have a number of issues with my app that I have no way of fixing because I have no clue what is going on, because I feel that they are iOS 5 issues, not mine.
Was there an iOS 5 conversion manual I missed? Or did they just change everything for fun, and want us to figure out where all the easter eggs were?
Here is another issue I am experiencing (that I have wasted so much time trying to fix), that DON'T EXIST AT ALL when I simply say that I want to run the app in good ol' 4.2:
Modal view
My app is a simple reader app. I have a book reading view that displays text with a UIWebView. One of the features I have been working on involves the ability to take notes as you read. This is achieved by hitting a button, and presenting a modal view. Yes, a modal view. The most simple pre- iOS 5 thing you could possibly do. Now, when I dismiss my modal view, just by hitting cancel, and simply dismiss the view, when I get back to my reader view, the navigation bar at the top is pushed up half way off the screen! This doesn't happen in 4.2, but there it is in iOS 5!
What can I do to get this issue resolved?
Thanks for your help.
Ok, I was just able to figure out what in the blazes was going on. I had the shouldAutorotateToInterfaceOrientation value set to a BOOL variable, so that when the modalView was coming back, it didn't know the state/size of the status bar. Fixed that, and the problem disappeared.
I have the feeling it has something to do with the way you present and dismissing the modalview. Apple introduced a new method to present views. May you try using theses instead of the old ones and see if it fixes your problem.
So here is what you do:
change this method:
presentModalViewController:animated:
into the new preferred method introduced with iOS 5:
presentViewController:animated:completion:
Depending if you are using dismissModalViewControllerAnimated:to dismiss your view, change it into dismissViewControllerAnimated:completion.
This methods also have completion handler which is very useful to do some extra work after the view has been presented/dismissed. Maybe that also helps with your other issue. Let me know if that might helped.
A major change in iOS 5 is that the navigationController property of UIViewController is no longer set for modal views. Instead, there is a new (not present in iOS 4) parentViewController property. So where you're using navigationController in a modal view you need to change the logic to something like:
UIViewController* parent;
if ([self respondsToSelector:#selector(parentViewController)]) {
parent = self.parentViewController;
}
else {
parent = self.navigationController;
}
(That's from memory, so I can't guarantee that every t is dotted and every i crossed.)
I was seeing this same clipping problem.
I found out that the reason for my issue was that I set the content size within the modal dialog (something I did for my iPad layout), so removing these two lines seemed to fix the issue:
CGSize size = CGSizeMake(320, 480);
self.contentSizeForViewInPopover = size;
I thought the problem was fixed but it wasn't. After reviewing the code some more, cleaning the build, and retesting it turned out to be a shouldAutorotateToInterfaceOrientation which would return NO for all orientations, for a brief amount of time (flag == NO) while the app is loading (root controller). You want to at least return YES to one orientation like so:
- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return !self.flag ? UIInterfaceOrientationPortrait == toInterfaceOrientation : YES;
}
I have a UITextView which I create in Interface Builder for an iOS app. I checked (and double checked, and triple checked) that it is properly connected to the outlet in my code. I create a property and synthesize it, and when I run NSLog(#"%#", myTextView);, it returns the UITextView's properties, not null. However, when I try calling [myTextView setText:#"My Text."];, it doesn't change anything on the view. I have found many people with similar problems like this on Stackoverflow and other places on the internet, however none of the solutions there helped me. I am using Xcode 4.0.2 on Snow Leopard. I am attempting to do this in the -viewDidLoad method. What could be causing this issue?
If you need any more information about my code setup, post a comment and I will update this post.
Are you sure the whole text view is visible on screen, and that the font color is not the same as your background?
It is very likely that the view that is displayed on the screen is not the same view as myTextView points to. Check [myTextView superview] and make sure it's onscreen. Then look and see if you've accidentally covered it with something. Change other aspects like the backgroundColor. Also, check the frame and make sure it's not CGRectZero.
Developing an iPhone app.
I've got a really strange problem where, every once in a while, the status bar at the top of my app screen will turn solid black. Not like the black version of the status bar, but like a solid black rectangle with NO text/icons. It's very rare, but usually seems to occur after returning to the app via multi-tasking or from a locked device (the app has been running in the background). I've seen it occur on both 3GS and iPhone4. Here's a screenshot:
I can never reproduce it when trying, it just seems to eventually happen at some point (sometimes it will go for days without happening).
Once it does occur, the app seems to continue functioning fine, even with the status bar gone, except for when I do one specific action in the app which will cause everything to freeze up all the sudden (the app doesn't crash, but everything on screen is frozen and non-interactive). Without explaining the design in detail, the specific action that causes it to freeze up (after the bug appears) is performing a simple upload in the background to a SQL database. Resetting the app is the only way to fix the problem once the black status bar appears.
Anyone else ever experienced this? I can't find a single thread anywhere explaining similar behavior, and it's driving me nuts.
It happened once in my app when I called a drawing method in my custom subclass of UIView instance right before I added it as a subview to parent view.
The solution was apparently easy: add it as a subview first before sending/calling any custom drawing methods.
Examples:
CustomView *aView = [[CustomView alloc] init];
[aView drawSomething];
[self.view addSubview:aView]; //wrong approach
[aView release];
Should be:
CustomView *aView = [[CustomView alloc] init];
[self.view addSubview:aView];
[aView release];
[aView drawSomething];
The screenshot is missing, but what you describe sounds as though you've incorrectly implemented the use of Apple's built-in view controllers.
Both UINavigationController and UITabBarController will automagically shift all the content inside them down by 20-pixels, if they detect there is "supposed" to be a statusbar on screen at the moment.
My guess is that you have some code that is removing the statusbar, but which is kicking-in after the Apple code has already detected it and shifted everything down to accomodate.
The "fix" is to re-read the docs on Apple's classes very carefully and use them as Apple dictates (usually, people use them in ways that seem sensible - e.g. embedding them inside other views - but which Apple has expressly declared are unsupported. Sadly those classes from Apple are very fragile)
Are you holding a reference to a QLPreviewController instance? I was able to solve this problem in my app by creating a new autoreleased QLPreviewController whenever I need to display a file modally, as opposed to reusing the same instance over and over again.
I had a similar problem, which I described in this question here
If you have any, try removing any CGRect frame created by reference to:
[UIScreen mainScreen].applicationFrame]
and instead create the frame using a more manual definition. If that works, you can decide how to proceed from that point.