How to use presentModalViewController in iPad - iphone

I have created a Cartview and want to display this view as a modalview when i click a button on productview.How can i do this ?
Actually i did this like
UIViewController *nav=[[UIViewController alloc]initWithNibName:#"CartView-iPad" bundle:nil];
nav.modalPresentationStyle=UIModalPresentationFormSheet;
nav.modalTransitionStyle=UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:nav animated:YES];
CGRect frame=nav.view.frame;
frame.origin.x -= 75;
frame.origin.y = 100;
nav.view.frame=CGRectMake(frame.origin.x, frame.origin.y , 672, 393);
But the problem is the formsheet view is coming and my cart view is coming overt that i need only my cartview.Also i need a close button on the right to side of the cartview to dissmiss the modalview.

The problem may be that you're trying to set the frame of the modal view controller manually. This is, as far as I know, not recommended. The UIModalPresentationFormSheet option already indicates the desired size of the modal.
As for a back button, you should add a navigation bar with a back button in your CartView-iPad-xib-file. To make it work you have to make a subclass of UIViewController (example: CartViewController) which will handle the back button press. Right now nav is just a normal UIViewController which has no idea what to do with the actions in your xib-file.
Then in your new view controller, you can make a function like this that you connect your back button to:
- (IBAction)backButtonPressed
{
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}

Related

Whats the difference between a destination vc and a source vc?

im trying to learn how to perform custom segues so i can have a game menu, and when i searched on the web it seems that you have to make a custom segue class, and override -(void) perform and in that method you have to specify a made up destination vc and a source vc. and establish its location and stuff. This was the one of the code things i saw on the internet.
#implementation FromTopReplaceSegue
-(void)perform{
UIViewController *dst = [self destinationViewController];
UIViewController *src = [self sourceViewController];
[dst viewWillAppear:NO];
[dst viewDidAppear:NO];
[src.view addSubview:dst.view];
CGRect original = dst.view.frame;
dst.view.frame = CGRectMake(dst.view.frame.origin.x, 0-dst.view.frame.size.height, dst.view.frame.size.width, dst.view.frame.size.height);
[UIView beginAnimations:nil context:nil];
dst.view.frame = CGRectMake(original.origin.x, original.origin.y, original.size.height, original.size.width);
[UIView commitAnimations];
[self performSelector:#selector(animationDone:) withObject:dst afterDelay:0.2f];
}
- (void)animationDone:(id)vc{
UIViewController *dst = (UIViewController*)vc;
UINavigationController *nav = [[self sourceViewController] navigationController];
[nav popViewControllerAnimated:NO];
[nav pushViewController:dst animated:NO];
}
#end
i guess this is supposed to make a segue that appears from the top going down or something. but i have a few questions like, what is a source and dest vc, and also in the part where the code says dst.view.fram=CGRectMake(dst.view.frame.origin.x, 0-dst.view.frame.size.height,
what the heck is that 0 there, and shouldnt that be dst.view.frame.origin.y ?
well, anyways i wired this up and created a push segue from a button, but when i did this the segue only came to about 3/4 down from the top of the screen, and the bottom 1/4 was showing the bottom of my root view. and also when i tried pressing a button on my new vc after the segue the program crashes.
Any Info would help Please!
This is one of those things that aren't fully explained it looks like. Judging from your code, it looks like the "source view controller" is the root view controller(or parent view controller) and the "destination view controller" is the DetailViewController(or the child view controller).
Not sure if this confuses you more. Anyways, the parent/root view controller is the main view controller and it handles displaying of child view controllers. What I find interesting is that the creator subclassed the view of another class rather than presenting it.
Now 0 - self.view.frame.size.height = -320 on the y axis. Think of your main view as a piece of paper and think of the child view as a second piece of paper. Imagine placing the two pieces of paper one above the other(not on top.) The screen will only display the bottom piece of paper until you animate the "paper above it" down. Basically, he plans to animate from the top rather than the bottom(I guess I answered my own curiosity.)

How can i create a global navigation stack?

I want a global navigation stack. When the user changes tabs or navigates to a new view in the same tab, I want to push the new view onto the global navigation stack. I want the back button in the navigation bar to go back to the previous view, which is sometimes a different tab, and sometimes a different view in the same tab.
To achieve this effect, you could ditch the UITabBarController - and emulate the bar by using a custom view or customizing the standard UIToolbar.
Have one navigation controller with, with your customized toolbar always visible, and when buttons are tapped on it, just push the views you want onto the navstack.
You want all the UIViewController's in the UITabBarController to be loaded into the same UINavigationController?
So something like this:
___ RootViewController ___
| |
UINavigationController UITabBarViewController
instead of
RootViewController
|
_________ UITabbarViewController _____________________
| | |
UINavigationController UINavigationController UINavigationController
You should try "experimenting" with your own custom UITabBar
I suggest you to create a global array (NSMutableArray) that will hold NSInvocation objects. So every time you push view controller you need to create NSInvocation with navigation controller as target and popViewConrollerAnimated: as selector. If you're tapping the tab bar item you need to set tab bar controller as target and setSelectedViewController: as selector. You should also specify current view controller as parameter using
- (void)setArgument:(void *)buffer atIndex:(NSInteger)index
Then every time you pop your global stack you need just call [myLastInvocation invoke];
I Had similar issue. I did it like this :
To change the tab, use : say, you want to go at tab 2 and its 3rd view controller
self.tabBarController.selectedIndex = 2;
[self.tabBarController.delegate tabBarController:self.tabBarController didSelectViewController:
[[[self.tabBarController.viewControllers objectAtIndex:2] viewControllers] objectAtIndex:3]];
you could achieve the same by setting the left bar button of your UINavigationController as the button of your choice, Handle the action method and invoke the appropriate tabbar button on click event.
You need to do all that in your root view controller ...
ADDED:
You could not get the back button on the root view controllers (Navigation controllers;s root view associated with your tabbar instance) just by pressing the tabbar button.
you need to find the way to achieve this as you are not getting this from iOS So The movement you press the tabbar button your need to have the variable that store the previous selected index and a method that give the information for any tabbar by just passing the index ... So by using these two you could set the title of your left bar button of navigation bar and return to the previous tab by assigning the appropriate action method to the left bar button ...
I got it working. In my experience I was needed to have mainTabBarController and detailedNavigationController as two root controllers.
Those two methods of UIApplicationDelegate class work perfect:
- (void) showDetailedTab
{
CGRect normalRect = self.window.bounds;
CGRect rightRect = CGRectOffset(normalRect, normalRect.size.width, 0);
CGRect leftRect = CGRectOffset(normalRect, -normalRect.size.width, 0);
detailedNavigationController.view.frame = rightRect;
mainTabBarController.view.frame = normalRect;
[self.window addSubview:mainTabBarController.view];
[self.window addSubview:detailedNavigationController.view];
[UIView animateWithDuration:0.35 delay:0.0 options:UIViewAnimationCurveEaseOut
animations: ^{
detailedNavigationController.view.frame = normalRect;
mainTabBarController.view.frame = leftRect;
}
completion: ^(BOOL finished){
[mainTabBarController.view removeFromSuperview];
}];
}
- (void) showMainTabBar
{
CGRect normalRect = self.window.bounds;
CGRect rightRect = CGRectOffset(normalRect, normalRect.size.width, 0);
CGRect leftRect = CGRectOffset(normalRect, -normalRect.size.width, 0);
mainTabBarController.view.frame = leftRect;
detailedNavigationController.view.frame = normalRect;
[self.window addSubview:mainTabBarController.view];
[self.window addSubview:detailedNavigationController.view];
[UIView animateWithDuration:0.35 delay:0.0 options:UIViewAnimationCurveEaseOut
animations: ^{
mainTabBarController.view.frame = normalRect;
detailedNavigationController.view.frame = rightRect;
}
completion: ^(BOOL finished){
[detailedNavigationController.view removeFromSuperview];
}];
}
I think this solution is better then emulating of tab bar, since it doesn't break UIViewContoller's life cycle.

Tab Bar controller is not accessible

I have created a tab based application for iphone. when the 1st tab presses a first view will present. this view contains a button, on pressing it another view loads.
Code is:
-(IBAction)buttonPressed: (id) sender
{
Cities *cv=[[Cities alloc] initWithNibName:#"Cities" bundle:nil];
cv.modalTransitionStyle=UIModalTransitionStyleCoverVertical;
[self presentModalViewController:cv animated:YES];
[cv release];
}
Now problem is that this view is loading in whole screen so that I am not able to access tab bar.
I have set the frame for this view and the view is loading in this frame,
-(void)viewWillAppear:(BOOL)animated
{
self.view.frame = CGRectMake(0, 0, self.view.frame.size.width, 400);
}
but in remaining part white screen is appearing means tab bar is not accessible.
I want that whatever will be load at any time tab bar should be always accessible.
Please help me out.
Add
cv.modalPresentationStyle = UIModalPresentationCurrentContext;
Have you tried using UINavigationController inside your tabbar to dig inside your UIViewControllers??
for Ref : Adding NavigationController to Tabbar
do you really need a viewController Class for what you are trying to display??
if der's no core functionality being used, i think it will be much easier with UIView.
Happy Coding :)

iPhone's UITabBar as part of application window; problems when rotating device

I have an iPhone application that's using Navigation Controller to display the top bar (with title and back button, and such...).
I added a UITabBar to the application window, that enables to switch between the parts of it. Instead of adding the tab bar to each of ViewController's view I added the bar to app window.
(When I had it in the ViewController, switching between controllers made the tab bar to swipe left/right, when animated pop/push occured, together with whole view).
So, I added the UITabBar to the MainWindow.xib, and tied it to the app delegate's variable. In my didFinishLaunchingWithOptions method, I added the following code:
[self.window addSubview:navigationController.view];
CGRect frame = navigationController.view.frame;
frame.size.height -= tabbar.frame.size.height;
navigationController.view.frame = frame;
tabbar.selectedItem = [tabbar.items objectAtIndex:0];
to resize the main (navigationController's) view, in order to make the TabBar visible.
The problem shows up when I rotate the device -- my view gets stretched to full window and I loose the ability to show the TabBar.
I added a - (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation) fromInterfaceOrientation method to my ViewController, with the following code:
- (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
CGRect frame = self.view.frame;
frame.size.height -= [AppState shared].tabBar.frame.size.height;
//frame.origin.y = [AppState shared].tabBar.frame.size.height;
//frame.origin.x = 100;
self.view.frame = frame;
frame = [AppState shared].tabBar.frame;
frame.origin.y = [UIScreen mainScreen].bounds.size.height - frame.origin.y - frame.size.height;
[AppState shared].tabBar.frame = frame;
}
It resizes the view, and moves the tab bar to up/down part of the view (I allow only Portrait/Portrait upside down orientations here). The problem is, my TabBar is turned upside down as well, and also, it's no longer clickable.
It looks like the image below:
Anyone knows how to handle this kind of situation? Or, how to make the tab bar not tied to view controller, but also able to handle interface's rotation smoothly?
You are using the tabbar in an unintended way. You seem to be using the UITabBarView as an uncontrolled element of other views. That is not it's function.
The UITabBarView should be controlled directly by a UITabBarController which in turn should be controlling all the view controllers for the views displayed in the tabbar i.e. the tabbar controller is a type of navigation controller that controls subcontrollers.
Suppose you have three tabs and the third one is a navigation controller. Your controller hierarchy would look like this:
TabbarController:
-->tab1ViewController
-->tab2ViewController
-->tab3ViewController(UINavigationController):
-->rootViewController-->secondViewController
You are trying to move and manage the tabbar view without its controller and the proper controller hierarchy. That isn't going to work.

iOS -- how do you control the size of a modal view controller?

I am presenting a modal view controller. If it matters, it is scrolling up from the bottom. How can I control what portion of the screen it occupies?
EDIT: I have the following in the modal view controller. It's not helping.
- (void)viewDidLoad {
TestResultView *trv = [[TestResultView alloc]initWithTest: [Model m].currentTest];
self.view = trv;
trv.frame = CGRectMake(0, 320, 320, 160);
[trv release];
[super viewDidLoad];
}
You can modify the frame of the view controller, but if you're using UIViewController's -presentModalViewController:animated: method, the view behind will be unloaded once your modal view is finished animating onto the screen (This assumes you're on an iPhone) and you'll see a white screen where your background view should be. iOS assumes that your modal view controller will be a full-screen view controller, and dumps the other view to save memory.
If you really want to show a view over part of the screen, you should instead add the UIView (no UIViewController) to your current UIViewController's view as a subview, and then animate it onscreen yourself. I think something like this would work in your UIViewController class that will present the view:
// Add the view as a subview and position it offscreen just below the current view
UIView *myHalfView = [[UIView alloc] initWithFrame:someAppropriateFrame];
[self.view addSubview:myHalfView];
CGRect offScreenFrame = myHalfView.bounds;
offScreenFrame.origin = CGPointMake(0.0, CGRectGetMaxY(self.view.frame));
// Now animate the view upwards
[UIView beginAnimations:nil context:nil];
// Move the view upwards the height of your sliding view so it's entirely onscreen
myHalfView.center = CGPointMake(myHalfView.center.x, myHalfView.center.y - myHalfView.bounds.size.height);
[UIView commitAnimations];
[myHalfView release];
For bonus points, you could fade the view in by setting
myHalfView.alpha = 0.0;
before the UIView animation block, and setting
myHalfView.alpha = 1.0;
inside the block after animating the center property.
When you're done, you can do something similar but in reverse to slide the view offscreen. You can add an animationDidStop selector to the UIView animation block to be notified when the view has slid off screen so that you can remove it from the view hierarchy.
From an aesthetic point of view, you should also be careful how you do this since having a view slide up is a standard behavior, and if your view looks like a normal view but stops halfway, users may feel (even briefly) that the app has frozen. They'll figure it out, but it will leave a bad feeling about your app if not handled carefully. Mainly, I would avoid using standard full-screen cues like including a UINavigationController at the top of your view to help users understand what's going on. Half-sheets tend to be UIActionSheets on the iPhone, so think in that direction.
That is nice, the above accepted answer explains a nice hack to present subViews which feel like ModalViews, but what if it is an iPad, and i can indeed give it a modalViewController which doesnt cover the entire screen.
In case of iPads, I dont think the underneath view will be unloaded. ( because there are options where we can present the modalView on iPads, which dont cover the entire screen )
ModalViewController in the end is a controller itself, and like any other controller has a root view, whose properties can be editted, if we can get hold of it.
Here is what will give you a custom frame of the ModalView :
MyViewController *viewController = [[MyViewController alloc] init];
viewConroller.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:viewController animated:YES];
//superView of viewController's view is modalViewController's view, which we were after
viewController.view.superview.frame = CGRectMake(x,y,w,h);
//x y w h - can have desired values.
I would add to #dsaw's answer that the superview of the modal view does not seem to rotate its coordinate system in landscape mode. Here is the code that I used in my own app:
MyViewController* modalVC = [[MyViewController alloc] init];
modalVC.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:modalVC animated:NO];
CGRect r = CGRectMake(self.view.bounds.size.width/2 - 236,
self.view.bounds.size.height/2 - 130,
472, 260);
r = [self.view convertRect:r toView:modalVC.view.superview.superview];
modalVC.view.superview.frame = r;
While the superview may not rotate itself with the iPad, it does seem to do the right thing and keep the modal view centered if I rotate the iPad after showing the modal view.