Can I use pushViewController with UISegmentedControl? - objective-c

I want to use pushViewController with UIsegmentedController to push to other view and xib.
Can I do that in xcode 4 ??? If I can , Could you guide me please ?
Here is some code that I try.But won't work.
-(IBAction) segmentedControlIndexChanged:(id)sender
{
if ([sender selectedSegmentIndex] == 0)
{
BDshelveController *shelve_page = [[BDshelveController alloc] initWithNibName: #"BDshelveController" bundle:nil];
}
else if([sender selectedSegmentIndex] == 2)
{
BDlibraryController *lib_page = [[BDlibraryController alloc] initWithNibName:#"BDlibraryController" bundle:nil];
[self.navigationController pushViewController:lib_page animated:YES];
}
}

yes you can, these are the things you could check
you missed segmentedIndex=1 in your code.
you missed to call pushViewController when selected segment=0
Or it is more likely that self.NavigatonController is nil
Your segmented control has not been connected valuechange to your action
If self.navigationController is nil, it depends on how you initialize your app, if your app is navigation bar driven, then this code in your AppDelegate should resolve the issue:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:yourRootViewController]; // <-- depends if you have storyboards, xib etc...you should this already initialized
[self.window addSubview:navController.view];
[navController release]; // <-- depends if you have ARC
[self.window makeKeyAndVisible];
return YES;
}
Otherwise I suppose you can initialize it where you are, by giving self as root controller.
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:self];

Related

Managing navigation controllers / view controllers

Not sure how to title this question, but i'v got such a problem: Up until now i my app runs mainly in one navigationcontroller with table views. But now i'm trying to integrate dropdown settings menu, and can't get it properly done.
The way i'v done now and it works
The changeController is called from one button. ChangeController is in appdelegate.
- (void) ChangeController
{
self.window.backgroundColor = [UIColor blackColor];
DropDownExample *e = [[DropDownExample alloc] initWithStyle:UITableViewStyleGrouped];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:e];
[e release];
[self.window addSubview:self.navigationController.view];
self.window.backgroundColor = [UIColor blackColor];
[self.window makeKeyAndVisible];
}
But this approach has consequances - there is no transition if button is pressed, the settings menu appears instantly, you cannot go back via navigation bar above (nothing there).
So how to do this properly?? I'm new to ios, so just tell me the whole idea how to do this.
Didfinishlaunchingwithoptions method from appdelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease
];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
TableViewController *tableVC = [[TableViewController alloc] initWithNibName:#"TableView" bundle:nil andType:CONTROLLER_TYPE_FIRST];
UINavigationController *navC = [[UINavigationController alloc] initWithRootViewController:tableVC];
self.navigationController = navC;
[tableVC release];
[navC release];
self.window.rootViewController = _navigationController;
[self.window makeKeyAndVisible];
return YES;
}
Ok, here's the answer. Write the method changeController in the same class where the Button exists which calls changeController
In the method, write this.
- (void) ChangeController
{
DropDownExample *e = [[DropDownExample alloc] initWithStyle:UITableViewStyleGrouped];
[self.navigationController pushViewController:e animated:YES];
[e release];
}
What you want is to insert new UIViewController on the top of the present Stack. If you would be having a navigation Bar at the top by default then there would be a back Btn by default, which would pop up that controller.

How to perform Segue in AppDelegate?

I am trying to complete an application on IOS 5.1 with Storyboard. Basically I am doing a dropbox app. Since I am using Dropbox SDK link to Dropbox is handled in AppDelegate.m. User has the option of be able to unlink from a session and link again in different View Controllers. So every time user link and unlinked app has to switch view from Appdelegate to a view controller that is unconnected to rootviewcontroller
In original Dropbox's example Dropbox handled transition like following code
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
if ([[DBSession sharedSession] handleOpenURL:url]) {
if ([[DBSession sharedSession] isLinked]) {
[navigationController pushViewController:rootViewController.photoViewController animated:YES];
}
return YES;
}
return NO;
}
But I am using Storyboard with Navigation Controller and any of the following methods are not working I put methods in comments.
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
if ([[DBSession sharedSession] handleOpenURL:url]) {
if ([[DBSession sharedSession] isLinked]) {
NSLog(#"App linked successfully!");
// At this point you can start making API calls
/*UIViewController *viewController = [[UIStoryboard storyboardWithName:#"MainStoryboard" bundle:NULL] instantiateViewControllerWithIdentifier:#"MeetingViewController"];
[self.navigationController pushViewController:viewController animated:YES]; */
//[self performSegueWithIdentifier:#"xxxx" sender:self];
/* LoginDropboxViewController *loginController=[[LoginDropboxViewController alloc] initWithNibName:#"LoginDropbox" bundle:nil];
[navigationController pushViewController:loginController animated:YES]; */
}
return YES;
}
// Add whatever other url handling code your app requires here
return NO;
}
Here is the storyboard of the app
So how can I switch view in AppDelegate.h ?
Note: If I add a segue and name the segue lets say goToMeeting
[self performSegueWithIdentifier:#"goToMeeting" sender:self];
error I get is : No Visible #interface for 'AppDelegate' declares the selector performSegueWithIdentifier:sender
If you consider pushing view manually rather then segueperform following code most probably will work for you
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
if ([[DBSession sharedSession] handleOpenURL:url]) {
if ([[DBSession sharedSession] isLinked]) {
NSLog(#"App linked successfully!");
// At this point you can start making API calls
//push view manually
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
LoginDropboxViewController *ivc = [storyboard instantiateViewControllerWithIdentifier:#"LoginDropbox"];
[(UINavigationController*)self.window.rootViewController pushViewController:ivc animated:NO];
}
return YES;
}
// Add whatever other url handling code your app requires here
return NO;
}
You can do it like this:
UINavigationController *navigationController = (UINavigationController*) self.window.rootViewController;
[[[navigationController viewControllers] objectAtIndex:0] performSegueWithIdentifier:#"goToMeeting" sender:self];
This will only work if the index in viewControllers array matches the one of your view controller and if it exists of course. In this case is the first one (in the array and storyboard).
The segue ("goToMeeting") must not be attached to an action. The way you do this is by control-dragging from the file owner icon at the bottom of the storyboard scene to the destination scene. A popup will appear that will ask for an option in “Manual Segue”; pick “Push” as the type. Tap on the little square and make sure you’re in the Attributes Inspector. Give it an identifier which you will use to refer to it in code.
In my case i need to go to dashboard screen from appdelegate using segue, the code as below in objective c.
if([rememberMe isEqualToString:#"YES"]){
//Goto Dashboard
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
SWRevealViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"revealVc"];
self.window.rootViewController = vc;
[self.window.rootViewController performSegueWithIdentifier:#"sw_front" sender:self];
[self.window makeKeyAndVisible];
}else{
//Goto login
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
LoginViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"LoginViewController"];
self.window.rootViewController = vc;
[self.window makeKeyAndVisible];
}
Write inside your didFinishLaunchingWithOptions
Hope it helps some one.

NavigationBar not displaying properling when pushViewController

The problem is pretty simple to understand with pictures.
I have a UINavigationController that allow the user to switch between to views.
The first view contains a search bar and a table view like so :
The second is a basic view where information about the cell are display
When I click on the search bar, the navigation controller gets hidden and the search bar is now at the top.
Now, if I click on a cell, it goes to the second views, but the navigation bar is first hidden like below :
And then, it automatically appears like that :
I have tried a couple of things like show the navigation bar before pushing the next view controller but it is quite ugly..
Does anyone know how to have the show the navigation bar directly on the second view (like in the contact application)?
[UPDATE] : Code
AppDelegate.m (I'm talking about navigationcontroller2)
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
FirstViewController *viewController1 = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
SecondViewController *viewController2 = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
viewController1.managedObjectContext = [self managedObjectContext];
viewController2.managedObjectContext = [self managedObjectContext];
viewController1.viewController2 = viewController2;
UINavigationController *navigationcontroller1 = [[UINavigationController alloc] initWithRootViewController:viewController1];
[navigationcontroller1.navigationBar setTintColor:[UIColor lightGrayColor]];
UINavigationController *navigationcontroller2 = [[UINavigationController alloc] initWithRootViewController:viewController2];
[navigationcontroller2.navigationBar setTintColor:[UIColor lightGrayColor]];
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:navigationcontroller1, navigationcontroller2, nil];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
FirstView.m
- (void) searchBarTextDidBeginEditing:(UISearchBar *)theSearchBar {
[self.navigationController setNavigationBarHidden:YES animated:YES];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (!noResultsToDisplay) {
PinDetailsViewController *pinDetailsViewController = [[PinDetailsViewController alloc] initWithNibName:#"PinDetailsViewController" bundle:nil];
NSManagedObject *managedObject = [fetchedResultsController objectAtIndexPath:indexPath];
Pin *pin = (Pin *) managedObject;
[self.navigationItem setTitle:#"Pins"];
[self.navigationController pushViewController:pinDetailsViewController animated:YES];
[pinDetailsViewController updateWithPin:pin];
}
}
If you need anything else, just ask but I think it's all there.
Try to use this code in each viewcontroller.
- (void) viewWillAppear:(BOOL)animated
{
[self.navigationController setNavigationBarHidden:NO animated:animated];
}
- (void) viewWillDisappear:(BOOL)animated
{
[self.navigationController setNavigationBarHidden:YES animated:animated];
}
Before you push the new view controller, you should unhide the navigation bar:
[self.navigationController setNavigationBarHidden:NO animated:YES];
I had a similar problem with the position of my navbar. Mine was moving up behind the status bar, and I fixed the issue by manually setting the navbar frame:
-(void)adjustNavBarOrigin
{
CGRect r = self.navigationController.navigationBar.frame;
r.origin = CGPointMake(0, 20); // 20 is the height of the status bar
self.navigationController.navigationBar.frame = r;
}
I had to call this method in a number of places, including viewWillAppear: and didRotateFromInterfaceOrientation:, but it worked a treat :)
Hiding the UINavigationBar can disturb the properties sometimes. Try using the property alpha instead of hidden.

SIGABRT Error using NavController in the PopOverController

I have posted similar question previously, but this time I am providing some code for analysis. I am creating PopOverController in my AppDelegate.m file and I am adding a NavigationController variable which I want to pass to PopOverController.m file so that using that I want to push other views. Here is how I am creating the PopOver in AppDelegate.m
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
if([viewController isKindOfClass:[SecondViewController class]]){
NSInteger index = [[self tabBarController] selectedIndex];
CGRect buttonFrame = [[[[[self tabBarController] tabBar] subviews] objectAtIndex:index+1] frame];
PopOverViewController *popoverContentController = [[PopOverViewController alloc]init];
UINavigationController *navcon = [[UINavigationController alloc]initWithRootViewController:popoverContentController];
popoverContentController.contentSizeForViewInPopover = CGSizeMake(250, 85);
popover = [[UIPopoverController alloc]initWithContentViewController:popoverContentController];
NSLog(#"X:%f Y:%f",buttonFrame.origin.x,buttonFrame.origin.y);
[popover presentPopoverFromRect:buttonFrame inView:self.tabBarController.tabBar permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
}
}
And in my PopOverController.m I am trying to use the NavigationController to choose views like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
sendFeedback *sendEmailViewController = [[sendFeedback alloc]initWithNibName:#"sendFeedback" bundle:nil];
downLoad *downloadFilelViewController = [[downLoad alloc]initWithNibName:#"downLoad" bundle:nil];
if (indexPath.row == 0)
[self.navigationController pushViewController:sendEmailViewController animated:YES];
else
[self.navigationController pushViewController:downloadFilelViewController animated:YES];
}
But when I click on my TabBar item for the PopOver I am getting this SIGABRT message :
Terminating app due to uncaught exception 'NSGenericException', reason: 'The content view controller argument must be the root of its associated view controller hierarchy.'
Any reason why this is appearing? Is there somewhere I am making a mistake in my code ?
UINavigationController *navcon = [[UINavigationController alloc] initWithRootViewController:popoverContentController];
you are trying to put a popover controller in a navigation controller. I don't think you want this.
To put navigation in popover, you should do this,
UINavigationController *navcon = [[UINavigationController alloc] initWithRootViewController:myViewController];
popoverContentController = [UIPopoverController initWithContentViewController:navcon]
and init the navigation controller with the viewController you want, like TableViewController or something else.

UITabBarController with a UIPopOverController with Multiple Views

I am working on a small app, according to the requirement the app should have a tabBarItem with 3 items. For this I have programmatically created the tabBarController in the AppDelegate.m file and added the 3 different viewControllers, instantiated them and everything is working good. I see the tabBarItems and all views are working. In one of the views lets say in SecondViewController I show a popOverController where I used a UITableView and populate it with items. When I click one of the items it should show another view lets say sendFeedback. Until there everything is working fine, but as soon as this sendFeedback is presented as the modal view, it occupies the whole app i.e it hides the tabBarItem.
I present the important pieces of code here for review:
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
UIViewController *viewController1 = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
viewController1.title = #"First";
UIViewController *viewController2 = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
viewController2.title = #"Second";
UITableViewController *tableView3 = [[tableViewController alloc]initWithNibName:#"tableViewController" bundle:nil];
tableView3.title = #"Third";
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1, viewController2, tableView3 ,nil];
self.tabBarController.delegate = self;
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
[viewController1 release];
[viewController2 release];
[tableView3 release];
return YES;
}
In my popOverViewController.m file I am checking which row is selected in the table according to that I present the view
#pragma mark - TableView Delegate Methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
sendFeedback *sendEmailViewController = [[sendFeedback alloc]initWithNibName:#"sendFeedback" bundle:nil];
downLoad *downloadFilelViewController = [[downLoad alloc]initWithNibName:#"downLoad" bundle:nil];
if (indexPath.row == 0)
[self presentModalViewController:sendEmailViewController animated:YES];
else
[self presentModalViewController:downloadFilelViewController animated:YES];
}
Can anyone guide me how to overcome this with the multiple views. In case if anyone requires more information from my side I would be glad to provide.
NOTE: It is the same with the other view (downLoad) as well
EDIT: Here is how I am initializing my PopOverController in the AppDelegate.m file
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
if([viewController isKindOfClass:[SecondViewController class]]){
NSInteger index = [[self tabBarController] selectedIndex];
CGRect buttonFrame = [[[[[self tabBarController] tabBar] subviews] objectAtIndex:index+1] frame];
PopOverViewController *popoverView = [PopOverViewController new];
popoverView.contentSizeForViewInPopover = CGSizeMake(250, 85);
popover = [[UIPopoverController alloc]initWithContentViewController:popoverView];
NSLog(#"X:%f Y:%f",buttonFrame.origin.x,buttonFrame.origin.y);
[popover presentPopoverFromRect:buttonFrame inView:self.tabBarController.tabBar permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
}
Thanks
Modal view controllers are used to "block" your application and fulfill a task before you can proceed. So modal view controllers are not what you want to use.
Instead wrap your controllers which have to be shown in the popover in a navigation controller. In the tableView:didSelectRowAtIndexPath: method you can push the corresponding view controller to the navigation stack.
To slove your problem:
At the place where you create the popovercontroller initialize it with a new UINavigationController. And the navigation controller you have to initialize with a rootviewcontroller namely PopOverViewController.m.
PopOverController *popoverContentController = [[PopOverController alloc] init];
UINavigationController *navcon = [[UINavigationController alloc] initWithRootViewController:popoverContentController];
popoverController = [[UIPopoverController alloc] initWithContentViewController:popoverContentController];
And in PopOverController.m
if (indexPath.row == 0)
[self.navigationController pushViewController:sendEmailViewController animated:YES];
else
[self.navigationController pushViewController:downloadFilelViewController animated:YES];