When does the UIViewController get deleted in ARC - objective-c

I am Working on a ARC based project. I got two ViewControllers. In the First ViewController I have a button, on pressing that button I am pushing the new ViewController.
I am doing it as follows:
SecondViewController *second=[[SecondViewController alloc]initWithStrVal:self.strVal];
[self.navigationController pushViewController:second animated:YES];
My problem is when I push the SecondViewController,and then create an object of the FirstView Controller in SecondViewController the dealloc method in FirstViewController gets called.
Where as the dealloc method doesn't get called if I only do the push and don't create an instance of FirstViewController in SecondViewController. As far as I have heard when I push a View Controller, dealloc shouldn't be called in the normal scenario, because the previous ViewController shoudn't deleted in the normal Scenario in ARC based project
EDIT:
The First ViewController is set in the app delegate as follows :
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
self.navController=[[UINavigationController alloc]initWithRootViewController:viewController];
self.window.rootViewController = self.navController;

Related

removing previous UIView

i have three view controller with three different XIB, let's say ViewControllerA, ViewControllerB and ViewControllerC and every view controller has UIView variable named view in it's property. so it would be something like this :
#property (readwrite, retain) UIView *view;
first, scene ViewControllerA loaded, then after i touched a button scene of ViewControllerB appears. but i deliberately not removing UIView of ViewControllerA from super view.
Then after i touched a button the scene navigate to ViewControllerC. here, before navigate to ViewControllerC i want remove UIView both of ViewControllerA and ViewControllerB from super view
removing UIView of ViewControllerB is not a problem, i can do something like this in ViewControllerB method :
[self.view removeFromSuperview];
but how can i remove UIView of ViewControllerA?
thanks
If you want totally independent of each other view controllers, you could switch them in appDelegate.window.rootViewController. Only create variable appDelegate that points to UIApplication.
And handle the animations by yourself.
Example:
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
UIViewController *controller1 = [ViewControllerA alloc] initWithNibName:#"ViewControllerA" bundle:nil];
UIViewController *controller2 = [ViewControllerB alloc] initWithNibName:#"ViewControllerB" bundle:nil];
appDelegate.window.rootViewController = controller1;
appDelegate.window.rootViewController = controller2;

Converting a category on UIViewController into a custom subclass

I had a class category that adds some methods to UIViewController. I needed to add some instance variables to the category, so I turned it into a custom UIViewController subclass, and added the instance variables. I then turned the UIViewController I was displaying into an instance of the new subclass.
Now I'm having trouble loading the new UIViewController when the application loads. I load the view controller from a nib in my AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
self.viewController = [[ATFIPresentationViewController alloc] initWithNibName:#"ViewController_iPhone" bundle:nil];
} else {
self.viewController = [[ATFIPresentationViewController alloc] initWithNibName:#"ViewController_iPad" bundle:nil];
}
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible]; //Crashes Here
return YES;
}
After doing so, an exception is thrown when I call makeKeyAndVisible on my application's window:
Terminating app due to uncaught exception 'NSUnknownKeyException', reason:
'[<ATFIPresentationViewController 0x6c497d0> setValue:forUndefinedKey:]:
this class is not key value coding-compliant for the key basicPicker.'
Where basicPicker is an IBOutlet to a UITextField. This is happening for every IBOutlet I've defined in my viewController. Why would making my viewController a subclass of my subclass of UIViewController, prevent anything loading from my nib? The "Files Owner" in the nib is ViewController, not ATFIPresentationViewController.
EDIT: Well, I got tired of trying to get this to work the "proper" and less typing heavy way. I got it to work by turning the extension into an NSObject, and pass the UIViewController to it. I posted what I was using this for on gitHub if anyone wants to take a look.
That error is occurring because your nib is trying to set a value onto an instance of a class that doesn't have a property by the name basicPicker. This is a solid indication that you're sending messages to the wrong type of object.
You need set the class of your File's Owner in your nib files to be the new UIViewController subclass you have created and not just the default UIViewController. Select File's Owner in your nib and you can change it in the right panel 'Utilities' third tab named Identity Inspector in Xcode, right at the top.

Jump between different viewControllers using UIButton?

I have a button that open another viewController(familyView) when clicked.
In familyView there is another button which suppose to bring me back to the mainViewController(ViewController.xib) but I don't know how to call the main viewController.
My method to call familyView
UIViewController* familyView = [[UIViewController alloc] initWithNibName:#"familyView" bundle:[NSBundle mainBundle]];
[self.view addSubview:familyView.view];
I hope you could help on how to call the main ViewController ? do I have to use the same method to call it? like this I mean:
UIViewController* mainView = [[UIViewController alloc] initWithNibName:#"viewController" bundle:[NSBundle mainBundle]];
[self.view addSubview:mainView.view];
If yes, is there a better way to implement this? in my demo project, I'm trying to make 7 views full with data and a button to go back and forth.
EDIT:
If I use UIView would that be best for me instead of using different viewControllers with their implementations and interfaces files?
My project will have views, and each view has data on it parsed from a different html page.
There are two method that can be used.
UINavigationController
Delegates
From your question it seems that a UINavigationController is the best option but I will show you both.
UINavigationController
When you load your mainViewController from your app delegate your going to need to wrap it in a nav controller like so:
AppDelegate.h
#property (strong, nonatomic) UINavigationController *navController;
AppDelegate.m
#synthesize navController = _navController;
//in didFinishLaunchingWithOptions:
UIViewController *mainViewController = [[MainViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
navController = [[UINavigationController alloc] initWithRootViewController:mainViewController];
self.window.rootViewController = nav1;
[self.window makeKeyAndVisible];
Now in your MainViewController you have the convince of UINavigationController.
When you want to push to a child from a parent you can simply do:
ChildViewController *child = [[ChildViewController alloc]...];
[self.navigationController pushViewController:child animated:YES];
If you in your ChildViewController and want to go back simply do:
[self.navigationController popViewControllerAnimated:YES];
This is the "Drill Down" technique.
(I know "Drill Down" has more meaning than simply that but it provides a good frame of reference.)
Delegate
Now the other method that you have is to setup delegates between the classes. So if your in childView and need to call your parent, you will have a channel to do so.
In your MainViewController.h setup it like so:
#import <UIKit/UIKit.h>
//This is our delegate
#protocol TalkToParentDelegate <NSObject>
//This is our delegate method
- (void)helloParent;
#end
#interface MainViewController : UIViewController <TalkToParentDelegate>
...
..
#end
In your MainViewController.m make sure add the delegate method.
- (void)helloParent {
NSLog(#"Hello child, let me do something here");
}
In your ChildViewController.h setup it like so:
#import <UIKit/UIKit.h>
//Add header of class where protocol was defined
#import "MainViewController.h"
#interface ChildViewController : UIViewController
//Create a property we can set to reference back to our parent
#property (strong, nonatomic) id <TalkToParentDelegate> delegate;
#end
Now, in your MainViewController.m , whenever you present your ChildViewController do this:
ChildViewController *child = [[ChildViewController alloc]...];
//Set the delegate reference to parent
child.delegate = self;
//present the view
Last but not least, no when you in your child you can call methods on your parent (MainViewController) like so:
[self.delegate helloParent];
So here are two methods that you can use.
I would like to note however, you can use these together. Say you had a UINavigationController but still needed a child to talk to its parent, you can setup a delegate so that's possible.
Hope this helps.

How change PickerView delegate from one controller to another one?

With the storyboard I've built one ViewController1 with an "Add" button. Click on add display a PopoverView (in ViewController2) with only a Picker within.
So my PickerView's delegate is in ViewController 2 but I want it in ViewController1...
Is there a easy way to do this so ?
Thanks
In your ViewController1 prepareForSegue method, try this:
if ([segue.identifier isEqualToString:#"MySegue"])
{
ViewController2* vc2 = segue.destinationViewController;
vc2.pickerView.delegate = self;
}
It basically assigns the delegate of the pickerview to ViewController1 before the segue is finished being called.
This of course is assuming your pickerview is setup as a property.
In your ViewController1.h file, change your interface header to this;
#interface ViewController1 : UIViewController <UIPickerViewDelegate, UIPickerViewDataSource>;
That makes your ViewController1 in charge of the delegates. Then add the methods you want in the ViewController1.m file. Also, set the delegate of the UIPickerView to your instance of ViewController1 with this:
[yourPickerview setDelegate:ViewController1];

Programming iOS: clarifications about Root View Controller

Through this question I would like to know if I understand well the notion of Root View Controller.
In iOS application, the Root View Controller (RVC) is the controller whose view gets added to the UIWindow application at startup, isn't true?
[window addSubview:rvcController.View];
[window makeKeyAndVisible];
Now, an UIWindow has also a rootViewController property. When running the previous snippet of code, does that property gets populated with the rvcController or do I have to set it explicitly?
Then, in a UINavigationController it is possible to set a RVC that is different from the previous RVC set for the entry point.
In this case, the first time I add a controller to the navigationController stack (pushing a new controller on it), does the framework set that controller as the RVC for the navigationController or do I have to set it explicitly through initWithRootViewController method?
Ya.. when I began iPhone dev.. the rootViewController thing threw me for a loop too. But it’s really straight forward.
when the app starts, I create a UIWindow object in my app delegate class. Also, in that class, I have a property of type UIWindow called window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UIWindow *w = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
self.window=w;
[w release];
// other code here...
}
I then create a UIViewController whose view will be the first view in the window hierarchy, this could be called the "root view controller".
The confusing part is...that often we create a UINavigationController as the "root view controller" and that navigation controller has an init method that asks for a "RootViewController", which is the first viewcontroller it will place on its stack.
So, the window gets a "root view controller", which is the UINavigationController, which also has a RootViewController, which is the first view controller you want to show.
once you sort that out, its all makes sense.. I think :-)
here is some code that does it all.. (taken from a project I have open in front of me)
//called with the app first loads and runs.. does not fire on restarts while that app was in memory
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//create the base window.. an ios thing
UIWindow *w = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
self.window=w;
[w release];
// this is the home page from the user's perspective
//the UINavController wraps around the MainViewController, or better said, the MainViewController is the root view controller
MainViewController *vc = [[MainViewController alloc]init];
UINavigationController *nc = [[UINavigationController alloc]initWithRootViewController:vc];
self.navigationController=nc; // I have a property on the app delegate that references the root view controller, which is my navigation controller.
[nc release];
[vc release];
//show them
[self.window addSubview:nc.view];
[self.window makeKeyAndVisible];
return YES;
}
Now, an UIWindow has also a rootViewController property. When running the previous snippet of code, does that property gets populated with the rvcController or do I have to set it explicity?
You have to set it explicitly, and if you do, you can remove the addSubview line, because that's handled automatically when you set a root view controller.
Then, in a UINavigationController it is possible to set a RVC that is different from the previous RVC set for the entry point.
Of course, a navigation controller's root view controller has nothing to do with that of the window.
In this case, the first time I add a controller to the navigationController stack (pushing a new controller on it), does the framework set that controller as the RVC for the navigationController or do I have to set it explicity through initWithRootViewController method?
initWithRootViewController is just a shortcut for initializing an empty navigation controller and pushing the first (root) view controller onto the stack. Note that rootViewController is not a property of UINavigationController, you would access it via [navController.viewControllers objectAtIndex:0].
firstly you can create A empty project in Xcode. after you add the new file on objectivec class view controller with xiv. now you can add to this code in appdeligate.m
and set the rootviewcontroller in appdeligate
NOTE:- ViewController.h import to the appdeligate.m
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
ViewController *viewcontroller =[[ViewController alloc]initWithNibName:#"ViewController" bundle:nil];
self.window.rootViewController= viewcontroller;
[self.window makeKeyAndVisible];
return YES;
}
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
ViewController *viewcontroller =[[ViewController alloc]initWithNibName:#"ViewController" bundle:nil];
self.window.rootViewController= viewcontroller;
[self.window makeKeyAndVisible];
return YES;
}