I have some code that works fine on my iPod Touch running some 4.0-series iOS as well as the simulator that comes with the iOS SDK 4.1. But when I call [UIViewController dismissModalViewController:] on an iPhone 2 running iOS 3.1.2 it get an infinite recursion, eventually crashing.
I have a view controller that opens a table view where the user selects a document to open. Upon selecting a document my table view controller's delegate calls the parent view controllers dismissModalViewController method. I think it is because I'm closing the view controller whose code is running that causes this.
dismissModalViewController is documented to be available in iOS 2.0 and later.
How can I close the UIViewController that's open from its own code?
I figured my problem might be heap corruption from some previous code. A way to debug that is to comment off snippets of previous code to see whether the bug would go away or come back. Almost immediately I found that I was calling dismissModalViewControllerAnimated: on the current view controller's parent controller. Why that works in iOS 4.x I have no idea. The problem I face is that I have two modal dialogs that I need to close simultaneously, which I cannot get working, but that is a different question.
Related
"viewWillAppear" not call in xcode 4.5 with iphone 4.3 simulator, but if it runs in iPhone 5.0 or iPhone 6.0 simulator, this method will be called.
why? and what can i do if i want to do something when the view of an controller will appear in ios 4.3?
I think it may be related to the "View Controller Abusing". Check if your container view controller is used correctly. You can refer to this post for detail.
Based on your comments, the problem appears to be the lack of container view controllers in iOS 4. As of 5+ you're explicitly meant to be able to add the view of any controller into the view of any other* and that will generate the appropriate view[Will/Did]Appear, along with all the other newer messages — viewDidLayoutSubviews, etc.
In 4 you weren't explicitly allowed to build container view controllers and there's no deliberate, specific backwards link that connects a view back to its controller.
As a result, when you add the navigation controller to your view it doesn't get viewDidAppear. Because it doesn't know that its view has appeared, it doesn't tell any of the controllers it contains that their views have appeared.
Probably the best you're going to be able to do is to hack around that by (i) checking if you're operating under iOS 4; and (ii) if so, posting artificial viewWillAppear/viewDidAppear/viewWillDisappear/viewDidDisappear to your contained controllers.
Based on personal experience, iOS 4 (at least in 4.3) does actually implement addChildViewController: but not to do what the later, documented version does. So despite it not being an entirely accurate functionality check I tend to use if([self respondsToSelector:#selector(presentingViewController)]) to determine whether I need to propagate these messages manually.
[*] and you should also call addChildViewController: to make sure all messages move correctly in all directions
I have a scenario where I present a modal view controller from the main window's rootViewController. While it is loading the contents of this modal, I am switching to another loading window which I make key and visible.
This window acts as a loading indicator and does not allow the user to interact with the app. When it is done loading, I switch back to the main window by making it key and visible. When I do this, the modal is force closed and the app is no longer able to present modals.
Interestingly enough, if I execute [UIWindow makeKeyWindow] when switching back to the main window, there are no issues. [UIWindow makeKeyAndVisible] is what's causing the issue. Is [UIWindow makeKeyWindow] an acceptable alternative?
This is iOS 5 only. No issues in iOS 6. I am not supporting iOS 4. Does anyone know what might be happening here?
I got the same behaviour, and as documentation states that makeKeyAndVisible method is a convenience method it seems to me legit to substitute makeKeyAndVisible call with working code:
[window makeKeyWindow];
window.hidden = NO;
Have no idea what's wrong, but it looks like a bug.
It is definetly bug in iOS 5 UIWindow implemetation. I faced this strange behaviour and Aleksey's answer is the way to go.
I made a universal application that contains NIB files for both ipad and iphone UI's. In my view controllers initWithNibName method I call UIUserInterfaceIdiomPad == UI_USER_INTERFACE_IDIOM() to detect whether the controller is running on iphone or ipad.
I then launch their respective nib files. When I run the app on iphone, it works fine, but when I run it on ipad it eventually crashes with a EXC_BAD_ACCESS error. This error occurs when I use a view controller to launch another view controller, which then launches another one in the navigation stack. This error occurs as soon as I click the view that belongs to the third controller of the stack.
I cannot distinguish a difference between the NIB files that would cause a crash. I have been working tirelessly to figure out why this is happening but I cannot fix this error. Does anyone have any insight into what might be going on?
Any advice on how to approach fixing this problem would be very appreciated.
The first thing you should do is enable the "All Exceptions" break point. This will often accurately tell you the line of code where the EXC_BAD_ACCESS is happening.
Next, I would turn on zombies and see where the over-release is happening. To do so, in Xcode, while holding the option key, click Product | Run.... In the ensuing window, add NSZombieEnabled to the environment variables list.
Then run. Do the normal things you do to cause the crash and see where the debugger lands. With any luck, it will stop where the problem is actually occurring.
When you get a EXC_BAD_ACCESS it means you're trying to access/release something that's already been released. If you're in a non-ARC situation, it normally means you've inadvertently released something when you didn't mean to, so just check for alloc/init and release balance. If, however, you're in an ARC situation, I would bet it has to do with not niling a delegate when a view controller gets released.
For example, if you have a MKMapView and have set its delegate to your view controller, you should nil its delegate when your view gets unloaded or dealloc'd. Otherwise, messages will continue to get set to it. Or, another possibility is that you've added your view controller as an NSNotificationCenter observer and didn't remove it as an observer when the view controller was unloaded or dealloc'd.
Another possibility is that you're re-using view controllers between the two versions of your universal app. If you are accessing anything by an identifier that doesn't exist in the nib for the iPad, that would cause a crash--though if you're using nibs as opposed to storyboards, that may not be an issue.
That's about all I can think of for now. Try to zero in on where it's happening and post code here if you still can't figure it out.
Best regards.
I'm working along with the book Beginning iPhone 3 Development, and am running into some issues on the "Pickers" app. I'm using Xcode 4.2, and I set it up exactly like they have it set up in their source code. All the code is the same, and all the outlet connections are the same. But, when I run my version, it launches a black screen, and the debugger says "Applications are expected to have a root view controller at the end of application launch."
There version in the source code runs just fine, and mine looks identical to it, but for some reason mine just won't run. I've Googled this issue and people have a bunch of workarounds, but I feel like there is something really simple in IB that I'm not seeing.
Any help would be great, thanks.
The iPhone 3 book is probably having you add the view of your view controller as a subview of the window, correct? Well, since iOS 4, UIWindow now has a rootViewController property and setting this property to your initial view controller is now the preferred way to get your first view controller on screen.
Basically replace something like this in -application:didFinishLaunchingWithOptions: in your application delegate...
[self.window addSubview:viewController.view];
with this...
self.window.rootViewController = viewController;
Quite a bit has changed since iPhone OS 3; beware as you proceed through the book.
Do you have the RootViewControllers XIB-file? And is it connected to the RootViewController Class (in designer)
My top level view immediately Pushes my SplashView in it's ViewWillAppear method. In some conditions, the SplashView pushes an additional view, which is properly popped. When this occurs the Top Level view never appears.
However, the code in the Top Level is running (it has a timer that occurs every minute which writes to the log). And if I trap it in Debug I can see the code executing. Additionally, in the Top Level ViewDidAppear if I log the [self navigationController].visibleViewController.nibName the name of the Top Level appears.
If I don't do the Push in the SplashView everything works fine.
The app is forced into Landscape mode, and each ViewController contains return UIInterfaceOrientationIsLandscape(interfaceOrientation); for the shouldAutorotateToInterfaceOrientation method.
I'm baffled and don't know what to do next. Suggestions?
While I did not exactly determine why this was occurring, I have resolved the problem. Here are some things I noticed in further debugging:
I noticed the message wait_fences: failed to receive reply: 10004003 in the log. Scanning blogs on this didn't help me much, but it led further down the path. References to it showed issues with UIAlertView, which I did have in the Splash view.
I added ViewDidAppear logic to the Splash view, then found this was getting called twice! I then added logic to act on this only once and my problem was solved!
So apparently there is some quirk with the View getting called twice that was creating my initial issue. References I found implied this was an 'old' OS issue, but I am using xCode 3.2.3 and SDK 4.0.2, so maybe it's back! Gee, I don't recall it doing this with SDK 4.0.1!