What happens after a viewController is pushed into another viewController - objective-c

I was just wondering while programming. I have got a rootViewController which creates an instance of a childViewController. This childVC is pushed onto my rootViewController through [self.navigationController pushViewController:childVC] from another childViewController (say childVC2). Now I was wondering what happens with my instance of childVC2. Does it get released? Because when returning from childVC to childVC2 I create a new instance of childVC2 and push it into my rootViewController. Obviously I do not have any use for the earlier instance of childVC2 so what happens with it or haw can I manually release it?

Yes if you are alloc the ViewController you have to release it .. the push will increase its reference count by 1 so you have to be sure that you are pop it to decrase the reference count .. and for the creating the instance define it in .h and when create it do it like this
if(yourViewController)
[yourViewContoller release];
yourViewController = [yourViewControllerClass alloc] init];
another opition is to make it autorelease and in this case you are not responsible to release the ViewController
yourViewController = [yourViewControllerClass alloc] init]autorelease];

Related

Does releasing a view controller releases all its properties?

I have a BaseViewController, which is a subclass of UITabBarController, and set up my views in this view controller.
-(void)setUpViews
{
FirstController *mainViewController = [[FirstController alloc] initAssignment:delegate.currentAssignment withMutableArray:myArray];
UINavigationController *firstNavController = [[UINavigationController alloc] initWithRootViewController:mainViewController];
SecondController *secondViewController = [[SecondController alloc] initWithNibName:#"SecondController" bundle:nil];
UINavigationController *secondNavController = [[UINavigationController alloc] initWithRootViewController:secondViewController];
self.viewControllers = [NSArray arrayWithObjects:firstNavController, secondNavController,nil];
firstNavController.tabBarItem.image = [UIImage imageNamed:#"blablabla.png"];
firstNavController.tabBarItem.title = #"Stream";
secondViewController.tabBarItem.image = [UIImage imageNamed:#"blabla.png"];
secondViewController.tabBarItem.title = #"Favourite";
}
Now I have another view controller, I call it ViewHandlerController, a subclass of BaseViewController. in my viewDidLoad in this viewHandler, i invoke setUpViews which is declared in BaseViewController. in the first screen of my app, when a Login button is pressed, I instantiate my ViewHandlerController, and presented my tabcontroller succesfully with nav controllers by using.
[[[UIApplication sharedApplication].windows objectAtIndex:0] addSubview:viewControllerHandler.view];
Inside my app. there is a logout button. I am using NSNotificationCenter to call my logoutMethod which is declared in my first screen. My question is, in this logoutMethod, how can I release the previously allocated objects to avoid memory pressure since the user can log in again (logIn - logOut -logIn)? since I'm using ARC, is setting my ViewController to NIL will do all the clean up?
EDIT: is removing my ViewControllerHandler from superview and setting it to nil helps releasing its subviews too?
Cheers
Well, answer for your question (not ARC) – no, basicaly view controller doesn't releases his properties when release. But you should nil your properties in viewDidUnload and (or) dealloc methods.
If you use ARC, you should notice that some actions can retain your controller, and it can never be deleted in some cases. Watch for methods, which takes object for delegate, they may not using weak references
Have a look at this Apple article about memory management.
You can just use autorelease in alloc methods or for (UIView *view in [self.view subviews]) {view release}; in dealloc.
In fact release is opposite operation to retain. When you do retain, you increase by 1 count of object instances in allocated memory. It happens when you call alloc, copy, new, mutableCopy. If you are using ARC you can't release objects, memory management is not your problem already.

Values not passed back after dismissModalViewController

I'm passing a string variable for the sake of testing (isLoggedIn) as well as an NSManagedObject (userObject). However, when I dismiss the VC and it comes back to the root, I do not have the new data that was set in the variables in the loginViewController.
LoginViewController *loginVC = [[LoginViewController alloc] initWithNibName:#"LoginViewController" bundle:nil];
loginVC.managedObjectContext = self.managedObjectContext;
loginVC.userObject = self.userObject;
loginVC.isLoggedIn = self.isLoggedIn;
[self presentModalViewController:loginVC animated:YES];
[loginVC release];
I later dismiss the view with:
[self dismissModalViewControllerAnimated:YES];
Update:
Ended up using delegates as someone suggested. I used the following post as a guideline:
UIViewController parentViewController access properties
I ended up using delegates as someone above suggested. I used the following post as a guideline:
UIViewController parentViewController access properties
I may not be following you properly so this could be irrelevant.
I am guessing you mean that:
You set your ivars after alloc/init
You make some changes inside LoginViewController
You expect those changes to be reflected in self.userObject and self.isLoggedIn of the class that instantiated LoginViewController
which may or may not happen if you act on the objects themselves or you reassign the pointers
e.g.
If you call self.userObject.name = #"Test"; inside LoginViewController then the change will be reflected in the class that instantiated LoginViewController and LoginViewController because the ivars are pointing to the same object in memory and you are manipulating the object.
OR
If you call self.userObject = theResultOfSomeNewFetch; then the change will not be reflected as you now have a pointer in LoginViewController that is pointing to a different userObject to the pointer in the class that called LoginViewController
Hopefully I have not lost the plot completely and this is somewhere near what you mean.

Delegate methods no longer called after converting to use Automatic Reference Counting

I've converted an app I'm writing to ios 5 and then using the inbuilt tool I converted it to use Automatic Reference Counting. There were no problems with ios 5 but after ARC conversion most of my delegate calls don't seem to be working. For example I have a subclass of UITableViewController with a .h file that looks like:
#interface UITableVCSubclass : UITableViewController <UITableViewDelegate, ... >
...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
...
#end
The Table View Delegate method tableView:didSelectRowAtIndexPath: no longer gets called when I select a row of the table. If checked that self.tableview.delegate == self, which it does. Any ideas why this has stopped working?
I had the same issue and couldn't find a good reference so hopefully this will help someone else. My working project didn't work after running the ARC refactoring doohickey. The view controller for my UITableView was being created on the fly and pushed without saving a reference, which is not something the conversion process looks for.
ARC was releasing the vc when it fell out of scope, so the view was visible but its delegate was gone. To fix it I added a strong property to the super to hold a reference to the new view controller and then I started receiving events again.
Changed from this:
MyViewController *myViewController =
[[MyViewController alloc] initWithNibName:#"MyViewController" bundle:nil];
To using the new property:
self.myViewController =
[[MyViewController alloc] initWithNibName:#"MyViewController" bundle:nil];

Objective-C - Unloading loaded view when it is swapped

What is the best way to do view management in a multiview application?
Right now I have this ViewSwitcher method/function that comes from a custom delegate I created.
The code is a whole bunch of if else like this
MyViewController *c = [[MyViewController alloc] initWithNibName:#"MyViewController" bundle:nil];
c.delegate = self;
self.myViewController = c;
[self.viewHolder insertSubview:c.view atIndex:0];
[c release];
That works fine, but when I visited the function a second time, is there going to be 2 instances of MyViewController now or just 1?
How do I unload MyViewController when I switch to another view?
Or is there a better way to manage my views?
Thanks,
Tee
If self.myViewController is a retained property, then there will be two instances of MyViewController up until this line:
self.myViewController = c;
... at that point the synthesized accessors will release the instances created in the first pass and then retain the newly created one. If the first instances has not been retained by another object, it will deallocate.

referencing an instantiated object in another class in objective C

I am working in xcode on an ipod app in objective C, and I have a field (navigationController) in one of my classes (rootViewController). How do I reference the instantiated rootViewController's navigationController from another class? For example, how would I do this if I want to reference the navigationController from the FirstViewController.m class?
I seem to only be able to find references for this to reference the application delegate.
If I want to reference the application delegate with FirstViewController, I just say:
MyAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
[delegate.navigationController pushViewController:childController animated:YES];
how do I do this for the rootViewController class instead of MyAppDelegate?
Based on the question you are asking, it seems that you want to call methods on the UINavigationController that is higher up in the stack. All UIViewControllers already have a property of navigationController which is the UINavigationController that is an ancestor to this ViewController on the stack.
So if you had a RootViewController, called root, that at some point did this
FirstViewController * first = [[FirstViewController alloc] initWithNibName:#"FirstView" bundle:nil];
[self.navigationController pushViewController:first animated:YES];
[first release];
Then first.navigationController == root.navigationController
So inside of first calling
[self navigationController]
will give you the same navigationController that first was pushed onto in the first place.
One object needs a reference to the other. There are many ways to make this happen. For example:
Have the same object create both and, since it knows them both, tell them about each other
Create them in the same nib and hook them up with normal connections
Have the owner of the nib one of the objects is in know about the other
Essentially, this is just a matter of designing your application properly so that the objects can be told about each other. There is no one magic thing you do.