I am trying to call a subview after a button is clicked on my root controller. The warnings appear in my AppDelegate (code is below), but I included the method from my root controller on how I call this new subview also in case that too has a problem.
the alerts that continue to come up are that the local declaration of navController hides an instance variable.
When I launch the application (which used to open fine) it now simply exits out...
#import "SEM2REDOAppDelegate.h"
#import "SEM2REDOViewController.h"
#implementation SEM2REDOAppDelegate
#synthesize window;
#synthesize navController;
#pragma mark -
#pragma mark Application lifecycle
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self.window makeKeyAndVisible];
SEM2REDOViewController *firstController = [[SEM2REDOViewController alloc]
initWithNibName:#"SEM2REDOViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc]
initWithRootViewController:firstController];
[self setNavContorller:navController];
[window addSubview:[navController view]];
[navController release];
[firstController release];
return YES;
}
then here is the method inside of my first view controller
- (IBAction)chooseFirstMeeting:(id)sender {
SelectRotationController *selectView = [[SelectRotationController alloc]
initWithNibName:#"SelectView" bundle:[NSBundle mainBundle]];
[selectView.navigationItem setTitle:#"Select First Meeting"];
[self.navigationController pushViewController:self.selectRotationController animated:YES];
self.selectRotationController = selectView;
[selectView release];
}
I know this may be an extremely simple question but I've just started this. doing an intensive study on programming in high school as an added course so I'd really appreciate any help!
Rename navController
UINavigationController *navController = [[UINavigationController alloc]
initWithRootViewController:firstController];
into something else. You can do this automatically by control-clicking word "navController", choosing "Refactor" from context menu, and then "Rename...".
Explanation:
The problem, I believe, in your local variable navController having the same name as instance variable under synthesized declared property navController.
Edit:
Also, this seems to be a typo:
[self setNavContorller:navController];
Correct:
[self setNavController:navController];
Related
I learn the ObjC program flow, so far I understand that chain begins in main.m->UIApplicationMain->AppDelegate->ViewController
The point I don't understand is to which method inside the ViewController the AppDelegate class transfers the focus...
I feel it is critical to understand this topic, so would be thankful for any clarifications.
I have this code of Appdelegate.m -
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
MasterViewController *masterViewController = [[MasterViewController alloc] init];
self.navigationController = [[UINavigationController alloc] initWithRootViewController: masterViewController];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
return YES;
and inside the ViewController there are these methods -
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.navigationController setNavigationBarHidden:YES animated: NO];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear: animated];
}
and others methods...
My questions are
To what method AppDelegate transfers control in MasterViewController. And does the control come back after MasterViewController "finished" its job or it is just looped?
How MasterViewController gets the xib name for initialisation (is it the same name as m file? i.e. what does it mean - nibNameOrNil bundle:nibBundleOrNil)
I see navigation controller involvement, however I don't understand how it is connected to viewcontroller....
If you catch my misunderstanding points - please be patient to explain... I feel that after this point I will be able to start...
(1) You're thinking about the logical flow in a procedural sort of way. The main run loop dispatches events down the responder chain. Your MasterViewController doesn't really 'finish'.
(2) The designated initializer for UIViewController is initWithNibName:bundle:. Your use of init here will not touch any associated nib file. If you wish to initialize MasterViewController from the nib, then you must use the designated initializer, e.g.
MasterViewController *masterViewController = [[MasterViewController alloc] initWithNibName:#"your-nib-name-goes-here" bundle:nil];
nibNameOrNil and nibBundleOrNil are just parameter names for the method. It's a tip to you that they may be nil. Take a look at the documentation for how the method behaves when those params are nil.
(3) UINavigationController is a subclass of UIViewController that presents content hierarchically. In this case, the application's window's root view controller is a navigation controller. In turn, that navigation controller's root view controller is your MasterViewController instance.
The documentation for UINavigationController describes it well.
I'm trying to replace my current viewController with a new one. I've been able to do this before but I'm having some issues with BAD_ACCESS.
This is the code that will run when I want to replace the current view with a new one.
(The function will be called using a local property "self.some_data" (nonatomic, retain))
-(void) labelSelected:(SomeDataObject*) some_data{
SomeViewController *viewController = (SomeViewController*)[[ClassManager sharedInstance] viewControllerForClassIdentifier:#"com.somename" fromPlistFileName:#"iPhoneScreenList"];
viewController.data = (NSObject*)some_data;
[some_data retain];
//[self.navigationController pushViewController:viewController animated:YES];
UINavigationController *tempNavigationController = self.navigationController;
[[self retain] autorelease];
[tempNavigationController popViewControllerAnimated:FALSE];
[tempNavigationController pushViewController:viewController animated:TRUE];
}
Here everything works fine. The issue is that if I release the new "viewController" it crashes. And if I choose:
[tempNavigationController popViewControllerAnimated:TRUE];
I get some really wierd behaviour where the controller never gets replace and I return to the rootController and the navigation bar has two layers of text on it.
And if I do this:
[tempNavigationController pushViewController:viewController animated:FALSE];
I get BAD_ACCESS and the application chrashes. It worked before but not anymore.
What am I doing wrong?
Thanks!
Use category for controller replace:
// UINavigationController+ReplaceStack.h
#interface UINavigationController (ReplaceStack)
- (void) replaceLastWith:(UIViewController *) controller;
#end
// UINavigationController+ReplaceStack.m
#import "UINavigationController+ReplaceStack.h"
#implementation UINavigationController (ReplaceStack)
- (void) replaceLastWith:(UIViewController *) controller {
NSMutableArray *stackViewControllers = [NSMutableArray arrayWithArray:self.viewControllers];
[stackViewControllers removeLastObject];
[stackViewControllers addObject:controller];
[self setViewControllers:stackViewControllers animated:YES];
}
#end
I'm new to iOS and Objective-C. I have an application that displays a table view, and opens a new view when click the user clicks on a row.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
DetailViewController *detailController = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:nil];
[detailController changeSubjectText:[subject_data_Array objectAtIndex:indexPath.row]];
//navigationController = [[UINavigationController alloc] initWithRootViewController:detailController];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.window addSubview:navigationController.view];
[self.window makeKeyAndVisible];
}
In my detail view I have coded:
-(IBAction)closeDetail:(id)sender {
NSLog(#"closeDetail");
[self.view removeFromSuperview];
}
But it's not working. Can anyone help?
Can anyone help me?
how i can close view?
download my code in --> http://www.vasuta.com/ios/multiview2.zip
open build and run click one row in "Bulletin Board" DetailView it's open click Close …..
why DetailView is not full screen and why can't close detail view?
i open it wrong or i close it wrong
help me please
didSelectRowAtIndexPath you can see in "GadgetBulletinsTVContoller.m" and close command you can see in "DetailViewController.m"
Thank you very much
ps. sorry for my english skill :(
Why are you creating that window object and why are you trying to add your subview to it?
if you want to add a subview you should add it to the parent, the tableview or the parent of the tableView.
a better idea would be to push a new view controller on the stack that would display the info you want to show.
Here is a tutorial that shows how to push a new view controller when selecting a cell in a tableview tutorial link .
EDIT:
in MultipleAppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions should look like below:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[MultipleViewController alloc] initWithNibName:#"MultipleViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
navController.navigationBarHidden = YES;
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
return YES;
}
In GadgetBulletinsTVContoller.h declare a protocol like below:
#protocol GadgetBulletinsTVControllerDelegate <NSObject>
#optional
- (void)showItemDetails:(id)selectedItem;
#end
and a delegate property:
#property (nonatomic, assign)id<GadgetBulletinsTVControllerDelegate>delegate;
In GadgetBulletinsTVContoller.m synthesize the delegate.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
should look like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if([delegate respondsToSelector:#selector(showItemDetails:)])
{
[delegate showItemDetails:[subject_data_Array objectAtIndex:indexPath.row]];
}
}
In FirstViewController.m tell the controller to implement the GadgetBulletinsTVControllerDelegate like this:
#interface FirstViewController ()<GadgetBulletinsTVControllerDelegate>
in viewDidLoad method tell the gadgetBulletinsController that his delegate is the FirstViewController class, like this:
if (gadgetBulletinsContoller == nil) {
gadgetBulletinsContoller = [[GadgetBulletinsTVContoller alloc] init];
gadgetBulletinsContoller.delegate = self;
}
and implement the GadgetBulletinsTVControllerDelegate's methods:
- (void)showItemDetails:(id)selectedItem
{
if([delegate respondsToSelector:#selector(showDetailsScreenForItem:)])
{
[delegate showDetailsScreenForItem:selectedItem];
}
}
In FirstViewController.h declare a protocol like below:
#protocol FirstViewControllerDelegate <NSObject>
- (void)showDetailsScreenForItem:(id)item;
#end
and declare a delegate property like below(don't forget to synthesize in .m file):
#property (nonatomic, assign)IBOutlet id<FirstViewControllerDelegate>delegate;
In MultipleViewController.xib select the FirstViewController screen and in outlets drag from the delegate to the fileOwner for setting the value of the delegate to the MultipleViewController(you can do this in code if you want to).
In MultipleViewController.m tell the MultipleViewController to implement the FirstViewControllerDelegate protocol like below:
#interface MultipleViewController ()<FirstViewControllerDelegate>
and implement the protocol method:
- (void)showDetailsScreenForItem:(id)item
{
DetailViewController *detailController = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:nil];
[detailController changeSubjectText:item];
[self.navigationController pushViewController:detailController animated:YES];
}
In DetailViewController modify the closeDetail method to look like this:
- (IBAction)closeDetail:(id)sender {
NSLog(#"closeDetail");
[self.navigationController popViewControllerAnimated:YES];
}
and voila, Your GadgetBulletinsTVController items details are pushed. You need to do the same steps for the other controllers from where you want to show details.
instead of removing the view from window just reload the basic view which contains all the table views using self.window.rootviewcontroller
EDIT
i got the solution by creating appDelegate what you have to do is just described below
First .h and .m file of AppDelegate Here (MultipleAppDelegate)
in .h add
#property (strong, nonatomic) id<UIApplicationDelegate>delegate;
in .m add
#synthesize delegate;
now where ever you like to add detailView just add below in .h and .m files as described
in .h file here(GadgetBulletinsTVContoller)
#import "MultipleAppDelegate.h"
and in interface one variable like this
MultipleAppDelegate *Mydelegate;
in .m file in viewDidLoad or loadView method
Mydelegate = [[UIApplication sharedApplication]delegate];
then at loading the detailView do this
navigationController = [[UINavigationController alloc] initWithRootViewController:detailController];
Mydelegate.window.rootViewController = navigationController;
[Mydelegate.window makeKeyAndVisible];
now at the detailViewController's .h and .m files
in .h file
#import "MultipleAppDelegate.h"
and in interface
MultipleAppDelegate *appDelegate;
in .m file in viewDidLoad or loadView method
appDelegate = [[UIApplication sharedApplication]delegate];
and on close button click
//Not required
//[self.navigationController popViewControllerAnimated:NO];
appDelegate.viewController = [[MultipleViewController alloc] initWithNibName:#"MultipleViewController" bundle:nil];
appDelegate.window.rootViewController = appDelegate.viewController;
[appDelegate.window makeKeyAndVisible];
That's all it will work fine only problem is that it take's 1 or 2 seconds to navigate and show the multipalViewController
enjoy Coding :)
Happy Coding :)
Is this a good way to set a custom ViewController as the rootViewController of the window?
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window.rootViewController = [[[CustomViewController alloc]init] autorelease];
[self.window makeKeyAndVisible];
return YES;
}
In most of Apple's examples they first declare a viewController property, and then:
RootViewController* theRVC = [[RootViewController alloc] init];
self.viewController = theRVC;
[theRVC release];
[self.window addSubview:self.rvc.view];
[self.window makeKeyAndVisible];
What is the diference between these two approaches and which is recommended?
The rootViewController property of UIWindow was recently introduced with iOS4. This new method seems to be the recommended approach advocated by Apple. Either approach works but I would stick with the new way of setting the rootViewController property only if you are not targeting early versions of iOS.
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;
}