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.
Related
I'm writing a navigation app for iPhone at the moment and I'm having a very weird crash issue and was wondering if anyone had come across (and solved) this issue.
I have two views, both of which contain UITableViews and one that uses cells loaded from a nib. When I push and pop from one view to the other, after a couple of presses (usually 7 to 10) with everything loading and displaying as it should the app suddenly crashes. The debugger shows that CALayer was the last thing running, but I don't use any custom implementation of this class.
My first thought is that I've over-released an object, but after two days of playing with the code I can't identify any zombies.
Does anyone know what's going on here? Can post parts of code if required.
UPDATE:
Looks like zombies are being created on UIView delegate methods, namely viewWillAppear, viewDidAppear, viewWillDisappear, viewDidDisappear. Will investigate further tomorrow. :D
What you can do is to set breakpoints at the dealloc methods of the related classes, and see if the crash happens in one of the method. And also usually by looking at the callstack when the crash is happening, you can tell whether it's a memory related crash or not.
I have created a window based application with the following
a TableViewController (Without a XIB file)
a ViewController (With a XIB file) <-- to be used as modal view
a CoreData model to store some data
I managed to load the application and populate the TableView with the data from the Entity, and I was able to scroll through all of the cells of the TableView, without any issues.
I added a UIBarButton item (rightBarButton) that causes a Modal View to appear for the user to input some data. The model view has a SAVE and CANCEL buttons.
The problem is once I press the Cancel Button, I go back to the TableView but if I try to scroll throgh the items in the tableview, the app crashes.
After 4 hours of searching Google and StackOverflow, I was not able to see why my app crash. I did however notice by the debugger that the ManagedObjectContext is set to NIL the second time I scroll the tableview (after the modalview is dismissed), although no data is changed and no insertion/deletion occured.
I tried using a timer to call reloadData as I found some answers on StackOverflow, but that did not work. I tried setting the ManagedObjectContext as a property with retain and removed all occurences of [myManagedObjectContext release] to avoid releasing it earlier than needed, but that did not help.
It seems that I am doing an obvious mistake, but I am not sure where.
Please help.
ivars do not become nil just because they're released somewhere else (at least not in iOS 4.3). So an over-release is not the specific cause of myManagedObjectContext becoming nil. Assuming you're using accessors to reference your ivars (and you should be), hand-implement setManagedObjectContext: and put a breakpoint in there to see who's calling it. Alternately, you can add a gdb watchpoint to myManagedObjectContext to see when the memory is changed.
You haven't indicated what the crash stack is when you crash. You should be focused on what memory you're accessing at the point of the crash, and ensuring that the crash is due to a memory violation rather than an exception. Check your debugger output. Often it will tell you what's happening.
I have a problem I can't locate clearly, maybe you can help me...
I have an iPad project, based on UINavigationController, most (but not all) of controllers inside are instances of UITableViewController, and everything works well...
Everything excepting that my application crashes randomly, sometimes after 10 minutes of use, sometimes after only 10 seconds...
It never crashes on the same view, never at the same time, making that difficult to reproduce.
In addition, it only seams to happen on device, I've never got this crash in the simulator.
The debugger doesn't help me very much, here is what it says:
-[UITableView autorelease]: message sent to deallocated instance 0x8e9800
And here is the call stack:
http://i.stack.imgur.com/JSCHx.png
Any idea ?
Thanks (and sorry for my english)
You're overreleasing a UITableView somewhere in your code. Are you calling release or autorelease on the UITableView inside one of your UITableViewControllers? You should only release objects that you 'own'. You get to own an object by using methods beginning with alloc, new, copy, or retain.
Please read the cocoa memory management guidelines for more info.
Useful links:
http://www.cocoadev.com/index.pl?MemoryManagement
http://www.cocoadev.com/index.pl?RulesOfThumb
At some point you are either releasing a UITableView instance that you do not own or you are failing to retain one at some point where you keep a reference to it (e.g. you store it in an ivar or a property declared assign rather than retain).
I have written about how to debug things like this on my blog:
http://loufranco.com/blog/files/Understanding-EXC_BAD_ACCESS.html
Basically, try these three things first:
Do a Build an Analyze and fix everything you see
Turn on Zombies, run your code -- it will tell you if you talk to dealloced objects
If that fails, try Debug Malloc, but that's way harder.
I apologize, after re-reading all my source code, I found ONE ViewController (I have around 20 ViewController), where I released an Outlet, in ViewDidUnload.
The reason that it crashed randomly is that I didn't understood well the mechanism of ViewDidUnload, it is called to release views (but not objects of controllers) when memory is low and view is not visible (ex: First ViewController of a NavigationController), and the views are re-loaded when the ViewController become visible again...
In simulator, memory is rarely an issue so ViewDidUnload is almost never called...
Problem fixed, thank you everyone for your help
To help with making sense of the trace, see iOS Debugging Magic (Technical Note TN2239) and Understanding and Analyzing iPhone OS Application Crash Reports (Technical Note TN2151).
Jeff
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.
I'm playing around with the iPad SplitView template and it was working fine before I started swapping out view objects in my RootViewController. When it was working fine, the application:didFinishLaunchingWithOptions method would be called and would setup my persistant store objects, then the RootViewController:viewDidLoad method would be called to populate my rootView with data from my store. I opened up IB and started swapping out view objects in my RootView and now the application:didFinishLaunchingWithOptions method never gets called, but the RootViewController:viewDidLoad method still does. Obviously, the app crashes because the viewDidLoad method depends on the successful execution of the didFinishLauchingWIthOptions method to setup the persistent store objects. Does anyone have any thoughts on what is causing this or how I can go about investigating what's causing this?
I'm obviously new to iPhone OS development, so I apologize if this questions is absurd in any way. Thanks so much in advance for your help!
This is propabaly caused by the fact that in MainWindow.xib, your application delegate object is not connected to File's Owner (UIApplication). You can open the MainWindow.xib and right click on your App Delegate to see if it has a connection in Referencing Outlet to File's Owner. If not, set it to. And this will fix your problem.
-viewDidLoad is not called from -application:didFinishLaunchingWithOptions:. They are independent. The call hierarchy could be summarized as:
load app; call -application:didFinishLaunchingWithOptions:
window is visible, load views of view controllers.
call -viewDidLoad.