Strange crash on selecting a UITableView cell - iphone

I am getting an EXC_BAD_ADDRESS crash when selecting a table's cell which should push a new view on the navigation controller.
Here is the stack trace (the CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION_ is always there):
alt text http://dl.dropbox.com/u/71415/crash_threads.jpg
I strongly suspect the new code I have added to load the initial data the app needs in a separate thread, partly because the init and loadView of the new view controller are being called and return fine. I am doing a [NSThread detachNewThreadSelector:#selector(loadData) toTarget:self withObject:nil]; in applicationDidFinishLaunching and then load a view showing a progress indicator. loadData does a [self performSelectorOnMainThread:#selector(setupMainUI) withObject:nil waitUntilDone:NO]; when data is ready. The UI (table and all) is loaded fine, the fresh data shows up great; it's only when a new view has to be pushed that the crash happens. Switching views via tab controller works fine as well.
Ideas?
Thanks.
Update:
This is what I am doing to load the new view controller:
NSArray *arrayForSection = [filteredGobos objectAtIndex:indexPath.section];
Employee *selectedEmployee = [arrayForSection objectAtIndex:indexPath.row];
if (self.employeeVC == nil) {
EmployeeVC *emplVC = [[EmployeeVC alloc] initWithEmployee:selectedEmployee];
self.employeeVC = emplVC;
}
[self.navigationController pushViewController:employeeVC animated:YES];

You have overreleased an object. Your app is signaled when trying to release the autorelease pool. That means something in the pool already was released and dealloced before. Try Build&Analyse or NSZombies to find the problem.
I don't think it has to do with your threading, as want you mentioned there looks right to me.

Related

EXC_BAD_ACCESS when popViewController

I am pushing BViewController from A properly. B contains a webview that starts loading a page when viewDidLoad. I am getting a strange behavior when popping B to A,
If webview finishes its load and then I execute popViewController (IBAction when touchUpInside on a toolbar button), popped to A so everything works perfectly.
However, if I popViewController immediately before webview ends its load, app crashes due to exc_bad_access. why? view is already loaded!
I checked on both situations viewcontrollers that are on navigation stack. Both cases with same result, 2 same objects, no difference!
-(IBAction)goBackOrg:(id)sender{
NSArray *viewControllers = self.navigationController.viewControllers;
[[self navigationController] popViewControllerAnimated:NO];
}
and for previously pushing it, I am using
if(!self.BController){
self.BController = [[BViewController alloc] initWithNibName:#"BViewController" bundle:nil anUrlDest:urlSocial];
}
[[self navigationController] pushViewController:self.BController animated:NO];
EXC_BAD_ACCESS occurs when you're trying to access an object that has been deallocated.
So the following could be your problem: when you pop ViewController B, it is being unloaded. If the web view loading finishes after ViewController B is unloaded, some piece of callback code is getting executed that is trying to do something with your ViewController or its view (or similar).
May be You are loading your webView on Thread and when you are using thread then you cannot do changes in UI otherwise your app will crash.
So just do this task on mainThread .

Apple Lazy Loading Images within a nav controller, reverts back to placeholder images

I implemented the LazyTableImages project (link) by Apple, but in my version I used RestKit to obtain the data and my UItableviewcontroller was push onto navigation stack.
So I eschew whatever apple does in the app delegate to get the xml. I dont think that's the problem. My problem is that when you back out of the UITableviewcontroller using either the nav back button or accessing another tabbar item and coming back, the images that were loaded there previously show up, but immediately it loads the placeholder image. Basically, the opposite happens.
It's like the UITableview cached data, so when you come back it interferes with the Lazy Table Images. I need to know has anyone implemented this code where they had to back out?
EDIT:
Looks like imageDownloader is not nil the second time, which prevents the image from loading. I'm still figuring out how to bypass it. Of course, I can just take out the condition, but I dont know if that is "bad" for performance.
imageDownloadsInProgress, a mutable dictionary, still has all of its data even if you back out. It has become a different question now, how do I delete imageDownloadsInProgress if a user hits back or strays from the current view.
imageDownloadsInProgress is retained, but I added [imagesDownloadsInProgress release] in the dealloc method, however I don't think that runs.
-(void)startEventImageDownload:(WhatsonEvent *)eventRecord forIndexPath:(NSIndexPath *)indexPath
{
EventImageDownloader *imageDownloader = [imageDownloadsInProgress objectForKey:indexPath];
if(imageDownloader == nil)
{
NSLog(#"%#",eventRecord.title);
imageDownloader = [[EventImageDownloader alloc] init];
imageDownloader.eventRecord = eventRecord;
imageDownloader.indexPathInTableView = indexPath;
imageDownloader.delegate = self;
[imageDownloadsInProgress setObject:imageDownloader forKey:indexPath];
[imageDownloader startDownload];
[imageDownloader release];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
}
}
The way I do it is to build my own cache and save the images in the user documents directory. When I call [tableView reloadData] (you are calling that, right?) it first checks for each cell if the image is there locally, otherwise it will lazily load them from the feed. Tell me if you need code for this.
The problem was that the self.imageDownloadsInProgess = [NSMutableDictionary dictionary] was placed in the ViewDidLoad method with the intention of resetting the dictionary every time. However, if you place the code within a view pushed onto a navigation controller, the ViewDidLoad only executes the first time (I'm not positive that is the case). I added the line to ViewWillAppear since it runs every time the view is placed on screen.

Simulate view unloaded because of low memory

I was following a sample code from Apple here: http://developer.apple.com/library/ios/#samplecode/TableSearch/Listings/AppDelegate_m.html#//apple_ref/doc/uid/DTS40007848-AppDelegate_m-DontLinkElementID_4
It is an example showing how to use SearchDisplayController to do search on a table.
The codes related to my question are:
in viewDidLoad -
- (void)viewDidLoad
{
self.title = #"Products";
// create a filtered list that will contain products for the search results table.
self.filteredListContent = [NSMutableArray arrayWithCapacity:[self.listContent count]];
// restore search settings if they were saved in didReceiveMemoryWarning.
if (self.savedSearchTerm)
{
[self.searchDisplayController setActive:self.searchWasActive];
[self.searchDisplayController.searchBar setSelectedScopeButtonIndex:self.savedScopeButtonIndex];
[self.searchDisplayController.searchBar setText:savedSearchTerm];
self.savedSearchTerm = nil;
}
[self.tableView reloadData];
self.tableView.scrollEnabled = YES;
in viewDidDisappear -
-(void)viewDidDisappear:(BOOL)animated
{
// save the state of the search UI so that it can be restored if the view is re-created
self.searchWasActive = [self.searchDisplayController isActive];
self.savedSearchTerm = [self.searchDisplayController.searchBar text];
self.savedScopeButtonIndex = [self.searchDisplayController.searchBar selectedScopeButtonIndex];
}
So, it says that it is saving the state of the search UI so that it can be restored if the view is recreated.
It also says that "it restore search settings if they were saved in didReceiveMemoryWarning."
So my understanding is, when memory is low, this view might be unloaded. It might be recreated again when user click on that tab to view that view.
So I want to simulate the low memory situation where my view gets unloaded, so that I can confirm that the logic where search terms get restored is working. But I failed.
I put a trace in viewDidLoad; it never fires more than one time, i.e., the view was never unloaded
I used the iPhone Simulator - simulate memory warning - the view never gets unloaded also.
To summary my question:
Will a loaded view in a tab bar contoller gets unloaded by iOS because it faces low memory?
If the answer to the above question is Yes, then does the iOS Simulator able to reproduce that?
I'm can't be positive about this answer but in my experience, it works this way.
If your UIViewController is registered as one of your UITabBarController's viewControllers and if the UITabBarController is the rootViewController of your UIWindow, the memory warning should be relayed to your UIViewController. If not I believe there a missing transition. To find out where, you could NSLog every UIViewController from the rootViewController to the UIViewController you want, and see where it stops.
Now, if you want to test the didReceiveMemoryWarning of your UIViewController, you can just call the method yourself, when another View is loaded or by using a timer.

crash when switching between tableviews using tab controller and MBProgressHUD

I have two tableviews. One loads when I select one tab, and the other loads when I select the other tab.
I use MBProgressHUD to allow for quick switching between the tabs as I pull the tableview datasource from the web using Objective Resource and that can take a little bit. So I throw up a HUD progress indicator waiting for the data to load.
This in turn has allowed me to quickly switch between tabs. But.... If I do it quick enough an exception occurs
EXC BAD ACCESS
with NSZombiesEnabled I get this:
2010-08-02 22:44:43.116 Film Fest[962:8703] *** -[MBProgressHUD release]: message sent to deallocated instance 0x85490b0
In both my tableviews I use two different custom tableviewcells.
What should be my next step to debug this?
... so I have moved the code to create the HUD from my viewWillAppear: method to viewDidLoad: and the crash went away.
// The hud will dispable all input on the view (use the higest view possible in the view hierarchy)
HUD = [[MBProgressHUD alloc] initWithView:self.view];
//HUD.graceTime = 0.5;
//HUD.minShowTime = 5.0;
// Add HUD to screen
[self.view addSubview:HUD];
// Register for HUD callbacks so we can remove it from the window at the right time
HUD.delegate = self;
// Show the HUD while the provided method executes in a new thread
[HUD showWhileExecuting:#selector(loadFilms) onTarget:self withObject:nil animated:YES];
however this doesn't really fix my issue as viewDidLoad only occurs once in a long while especially with the new multitasking. I need this HUD to fire the selector everytime the tableview appears.
Why is it not correct for me to have it occur in the viewWillAppear... is it because that can be loaded so much and I just kept on allocating the object? perhasp I should allocate in viewDidload and fire the
// Show the HUD while the provided method executes in a new thread
[HUD showWhileExecuting:#selector(loadFilms) onTarget:self withObject:nil animated:YES];
only in my viewWillAppear:?
Thoughts?
Find all the places where you init/retain/release/autorelease an instance of MBProgressHUD.
The NSZombie tells that this project receives a release message after it is being already deallocated (retain count is zero).
It will help if you will post some code - otherwise it is too difficult to help you...
EDIT:
As you have mentioned in your edit, it would be much better if you'd initiate the HUD only once per view controller (e.g. in viewDidLoad) and call to showWhileExecuting each time you need it (e.g. in viewWillAppear).
But it still doesn't explain the crash.
You you execute the entire code you have posted (as is) for a few times from the same instance of a view controller then you should have memory leaks. That is because I don't see where you release the old instance of HUD.
In addition, you are better set the delegate of the HUD to be nil right before releasing it and before calling the [super dealloc]; in the dealloc method of the view controller.
The last one might cause the EXC BAD ACCESS error.
One more thing, if the entire code you have posted is executed more than once then you should also have few HUD views under the self.view.
I don't know what HUD does in the background - maybe this causes the error...

how to release presentModelViewController stack in iphone?

I m Copying my code here below :-
-(IBAction)referencewindow:(id)sender
{
frmReferences *reference = [[frmReferences alloc]initWithNibName:#"frmReferences" bundle:nil];
[self presentModalViewController:reference animated:YES];
}
There are number of places I m using presentModelViewController and my problem is that stack shows memory leakage due to presentmodelviewcontroller.
when we use presentModelViewController to call other nib as above stated then it just override to the previous view but previous view is still in process thats why memory lekage problem is occuring so please tell me when i call other nib file using presentModelViewController then how to unload that previous view from memory while switch to other view and then on other view to next view.
You must release your viewController after call the presentModalViewController method like here:
- (IBAction)referencewindow:(id)sender {
frmReferences *reference = [[frmReferences alloc]initWithNibName:#"frmReferences" bundle:nil];
[self presentModalViewController:reference animated:YES];
[reference release];
}
There is more information here: Modal View Controllers
Your building a navigation hierarchy using present modal view? It could work but you need to released it sometime.
I think if you tried using normal memory management rules it would work out. Try going back from your views and they should be released, you'd see the memory go down in instruments.