Trying to understand NavigationController retain count for ViewControllers on its stack - iphone

I have an UITableViewController as the rootViewController for my navigatorController.
When I press a table cell I do the following:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
MessageHistory *msg = (MessageHistory *)[[self fetchedResultsController]objectAtIndexPath:indexPath];
ConversationViewController *chatController = [[ConversationViewController alloc]initWithNibName:#"ConversationView" bundle:nil andUser:msg.user];
[self.navigationController pushViewController:chatController animated:YES];
[chatController release];
But when I'm returning from the chatController (using the back button on the navbar) I get “EXC_BAD_ACCESS”
commenting
//[chatController release];
solves the problem. How? I thought when pushing to the navigationController adds a retain count and when pop from it release it?
Also I believe if I'm not including the release after pushing to the navcontroller I'm generating a leak.
Any idea what's happening here?

I've had this problem a few times, and almost went crazy trying to find the error.
In my case, I had a UIWebView in my second view with the UIViewController set as it's delegate. In my UIViewController dealloc method, I forgot to put webView.delegate = nil.
When the second UIViewController was popped and thus deallocated, the UIWebView was sending a message to it's delegate (the second UIViewController, which didn't exist anymore).
Don't know if this applies to you, but I spend days searching for this error, so perhaps it is of any help.

Related

didSelectRowAtIndexPath method does not load new View in iOS app code is inside

I have my first and normal view controller with a UITableView in it. The items that need to be displayed in those rows work perfectly.
Now comes the issue, if the user selects a row, I want a new view opened.
This view is called SecondViewController. so I have the .h, .m and .xib file named that way and it is of the UIViewController class.
I am using a CustomCell for the tableview could this be the issue?
I have #imported everything normally, and this is the code I am using in the method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
[self.navigationController pushViewController:secondViewController animated:YES];
}
What on earth am I doing wrong? I have been looking at questions here for hours but nothing seems to be working.
Are you sure that self.navigationController is not nil?
Try to log it, From your code your problem is probably that, your self.navigationController is nil.
This class is pushed from another or are you starting the navigation in this class? If you are starting it in this class, this is your issue, you need to call the navigation that you created and not the one that is supposed to be with your viewcontroller.

No visible #interface for 'UIWebView' declares the selector 'initWithNibName:bundle:'

First I want to say you that I'm totally new in Xcode so I'm a Newbie.
Then I also want to say you that I'm not able to speak English perfect...I'm learning it.
So, my problem is that I get the following error:
No visible #interface for 'UIWebView' declares the selector 'initWithNibName:bundle:'
I don't know why, I've already searched in many other forums (and this, too) for this, but the solutions there didn't help me.
I want to create a Table View that loads an UIWebView if I push a row.
That's my Code:
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (self.mehrWebView == nil)
{
UIWebView *temp = [[UIWebView alloc] initWithNibName:#"MyWebView" bundle:[NSBundle mainBundle]];
self.mehrWebView = temp;
}
[self.navigationController pushViewController:mehrWebView animated:YES];
}
I'm frustrated, I don't know how to continue.
I hope you can help me with my problem.
Thanks & Best Regards
The initWithNibName:bundle: method is an initializer of UIViewController classes, not UIView classes. On the other hand, UIWebView is a UIView class, so Xcode correctly tells you that UIWebView lacks the initWithNibName:bundle: method.
Moreover, you cannot push views onto the navigation controller's stack. You need to replace UIWebView with the type of the controller of the #"MyWebView" nib to make it work.

ViewController never gets deallocated

In my mind, myViewController should be deallocated around the time that I pop back to the root view controller with the following code, but I never see the deallocation message getting NSLogged.
If this should work, then what kind of problem can I look for in the myViewController's class that might cause it to get deallocated when I popToRootViewController?
Thanks.
The following gets called in my tableView:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
MyViewController *vc = [[MyViewController alloc] initWithNibName:#"MyViewController" bundle:nil];
[self.navigationController pushViewController:vc animated:YES];
[vc release];
}
UPDATE:
This code was perfect, but it was some bad memory management in my custom view controllers that caused neither to be released. I had some retained properties that should have been assign instead (or at least, that's the way I solved it). See comments for specifics.
When you use poptoviewcontroller then dealloc method will call for the topmost view controller in navigation controller. You can put a breakpoint in dealloc method of your current view controller and when you called popviewcontroller then your dealloc method gets called and release all the stuff/varaibles you have created in your view controller.
#JaySmith02 is right
it was some bad memory management in my custom view controllers that caused neither to be released. I had some retained properties that should have been assign instead (or at least, that's the way I solved it)
In my case the culprit was
#property (nonatomic, retain) id<TTSlidingPagesDataSource> dataSource;
From my viewController when I wrote
slidingPages.dataSource = self
I guess the dataSource retained my viewController and made a circular retention. The 'dealloc' of my viewController was never getting called.
Note: Under ARC dealloc does get called. Difference is you cannot call [super dealloc]
The solution:
#property (nonatomic, assign) id<TTSlidingPagesDataSource> dataSource;

In iphone app, with 3 viewcontrollers with UInavigationcontroller, from 2nd to 3rd view, dealloc is not called

I am posting a question since there are similar problems to mine, but not exact.
I am new to iphone app development.
I have 3 view controllers like below.
1 - Mapview controller is the 1st view controller and calls the 2nd table view controller by
[self.navigationContrller pushViewController:titlesViewController];
[titlesViewController release];
2 - titlesViewController is 2nd table view controller and in the DidSelectRowAtIndexPath method, it calls the 3rd view controller.
#implementation TitlesViewController
NSMutableArray *titleArray;
NSMutableArray *bidArray;
...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
...
[self.navigationController pushViewController:detailViewController animated:YES];
[webView release];
[detailViewController release];
[titleArray release];
[bidArray release];
NSLog(#"****** titlesviewcontoller didSelectRowAtIndexPath");
}
- (void)dealloc
{
[titleArray release];
[bidArray release];
[super dealloc];
NSLog(#"****** titlesviewcontoller dealloc");
}
#end
3 - detailViewController is the 3rd view controller to show detail info.
I did the Xcode profile->instruments->Memory leak, and there is a memory leak without
[titleArray release];
[bidArray release];
in the didSelectRowAtIndexPath in the 2nd table view controller.
I also noticed that with this app running in the IOS simulator, if I go to 3rd detail view from 2nd table view, the dealloc() method is not called, so there is memory leak without the 2 release codes for titleArray and bidArray. But if I go from the 2nd table view to the 1st view by pressing the Back button on the UINavitagation controller, the dealloc() is called. And so, no memory leak.
My question is do I really need the 2 release codes
[titleArray release];
[bidArray release];
in the didSelectRowAtIndexPath in the 2nd table view controller.
Is my observation correct?
I thought the dealloc() is invoked every time.
Thank you very much in advance.
You need to release ANYTHING you alloc. Nothing more. Nothing less. By explicit release, or by setting autorelease when allocating. If you don't alloc, you don't need to release : It's just a memory reference referencing nothing.
Why don't you put your global vars as member vars ? You should, that would be more clear. If it's not to make them available to other classes, well... Objective-C is not designed to do this. And anyway, using global vars is not recommended.

release after iPhone navigationController pushViewController

I am very confused at the following code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
RPSAdvisorViewController *pushThis = [[RPSAdvisorViewController alloc]init];
pushThis.opponentName = [opponentArray objectAtIndex:indexPath.row];
[self.navigationController pushViewController:pushThis animated:YES];
//[pushThis release];
}
The if the line [pushThis release] does not get commented out, the app would crash when I pop back out of that view. I thought I always need to released the viewControllers that I allocated, but this time the app won't let me.
I even tried testing for leaks in instruments like this without releasing pushThis, there are no leaks.
I am really confused, can some one tell me why I'm not suppose to release pushThis?
Edit1: The crash will produce this error message:
-[CALayer release]: message sent to deallocated instance 0x4e66b20
It appears that when the navigationController pops the view controller, it trys to send release to pushThis again, which was already released. If I don't release everything works perfectly, instruments does not show any leaks even if i repeatedly push and pop the view controller.
You have to release it because when you push view controller, navigation controller take ownership of that controller.
I think there might be some views hierarchy issue with your app.Can you please check that?
I can only guess that there is some problem with RPSAdvisorViewController. Can you try replacing it with a place-holder UIViewController and see what happens?