I've looked around and I can't for the life of me find a way to replace the backbarbuttonitem with a swipe gesture. I want to swipe left and have the app revert back to the previous view controller. Just to clarify I'm using a UINavigationController to manage all my View Controllers. Any ideas? Or is this not possible? Thanks!
I worked it out and now I feel stupid for asking this question! Here is the code I used:
I created a Swipe Gesture in the ViewDidLoad function:
- (void)viewDidLoad
{
[super viewDidLoad];
// -- EDIT Added the allocation of a UIGestureRecognizer -- //
UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(gotoPreviousView:)];
swipeRight.numberOfTouchesRequired = 1;
swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:swipeRight];
}
Then I simply created this...
- (void)gotoPreviousView:(id)sender {
[self.navigationController popViewControllerAnimated:YES];
}
Easy! Looked too far into it and the answer was staring me in the face. Hopefully if you don't know how, you'll see this and not make the same rookie error I did ha...
Related
I've tried setting the Info.plist 'View controller-based status bar appearance' to NO, I've tried calling
[[UIApplication sharedApplication] setStatusBarHidden:YES];
I've tried
-(BOOL)prefersStatusBarHidden{
return YES;
}
I've tried launching the picker with
[self presentViewController:picker animated:NO completion:^{
[[UIApplication sharedApplication] setStatusBarHidden:YES];
}
And still, there is a status bar overlapping the camera controls. It's only there in iOS 7 though.
The status bar doesn't show up any where else in the app. I feel like I'm missing an important piece of the puzzle here, and no amount of reading about the View Controller or UIImagePickerController has helped me find said puzzle piece.
I'm hoping some one else has a little insight into this problem. Thank you.
EDIT: My desired effect is that the Status Bar shows up every in the app, except on the camera picker and a few other "outside" (Email related) view controllers we use.
If you want to keep ViewController-Based Status Bar Appearance, subclass UIImagePickerController and override prefersStatusBarHidden and childViewControllerForStatusBarHidden.
#interface NoStatusBarImagePickerController : UIImagePickerController
#end
#implementation NoStatusBarImagePickerController
- (BOOL)prefersStatusBarHidden {
return YES;
}
- (UIViewController *)childViewControllerForStatusBarHidden {
return nil;
}
#end
Try this :
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[[UIApplication sharedApplication] setStatusBarHidden:YES];
}
in your appDelegate.
There's an additional setting you need to turn on, starting in iOS 7. In your app's Info.plist, add a line for View controller-based status bar appearance, a Boolean, and set it to NO.
The PsychoDad method works for me. I put the following
[[UIApplication sharedApplication] setStatusBarHidden:YES];
into the method viewWillDisappear of subclass of UIImagePickerController.
But the Alexandru Dranca method is better because in that way the status bar don't appear at all!
However I think this is a BUG of IOS 7...
"View controller-based status bar appearance" set to NO, works for me.
you should leave the
-(BOOL)prefersStatusBarHidden{
return YES;
}
and also add this
-(void)viewWillAppear:(BOOL)animated {
...
[self setNeedsStatusBarAppearanceUpdate];
...
}
I've been on this bug for repairing ToonPAINT for iOS7 and the thing that finally worked other than setting the two things in the Info.plist file (Status bar is initially hidden = NO; View controller-based status bar appearance = NO)
was to change the style of the status bar (even though I didn't want it shown at all); It was not enough to just hide the status bar; sounds like an iOS7 bug.
In the app delegate add:
-(void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController
animated:(BOOL)animated
{
[[UIApplication sharedApplication] setStatusBarHidden:YES];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
}
{NB .. UIStatusBarStyleBlackTranslucent is deprecated, probably use UIStatusBarStyleLightContent if trying this}
I think the answer to this question is "This is an iOS 7 bug". None of the methods here helped in our case, and several people have tried to fix this now.
I can't say what steps to reproduce this, but I've seen enough people out there with the same issue, that I think it's safe to say that this is in fact an iOS 7 bug. Most people can fix this problem with the multiple methods listed above. Rarely though, you can't fix it that way. I hope if you are reading this, you are not also one of those people.
This is what worked for me:
#implementation ViewController {
BOOL hideStatusBar;
}
- (void)showCamera {
UIImagePickerController *camera = [[UIImagePickerController alloc] init];
camera.modalPresentationStyle = UIModalPresentationCurrentContext;
camera.sourceType = UIImagePickerControllerSourceTypeCamera;
camera.delegate = self;
hideStatusBar = YES;
[self setNeedsStatusBarAppearanceUpdate];
[self presentViewController:camera animated:YES completion:nil];
}
-(BOOL)prefersStatusBarHidden{
return hideStatusBar;
}
In Xcode, I've got one ViewController segued to a second, and on the second I've got a 'go back' button:
The initial programming was:
- (IBAction)onBackButtonPressed:(id)sender {
[self dismissModalViewControllerAnimated:YES];
}
But as of iOS 6 the code has deprecated - what should I use then?
I'm a beginner, and basically want to programme a button which takes me back to the original ViewController from my second one.
The new method you could use is:
[self dismissViewControllerAnimated:NO completion:nil];
I am trying to change the action executed by pressing the backBarButtonItem of a Navigation Controller.
I know that i have to edit the backBarButtonItem before the next view (on which the button with custom behavior should appear) is pushed. So in the previous ViewController i added the following code, to push via segue:
#pragma mark - segue methods
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"SettingsToProfile"]) {
MyProfileViewController* myprofileVC = [segue destinationViewController];
myprofileVC.myProfile = myProfile;
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Settings_" style:UIBarButtonItemStylePlain target:myprofileVC action:#selector(popTOSettingsViewController:)];
} else {
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Settings" style:UIBarButtonItemStylePlain target:nil action:nil];
}
}
The title "Settings_" gets displayed correctly, but "target: myprofileVC action:#selector(popTOSettingsViewController:)" doesn't seem to have any effect at all.
Background:
MyProfileViewController is a View, where the user can edit his/her own information. Whenever the backbarbutton is clicked, i want to check if something in the GUI has been changed by the user. If thats the case, a UIAlterView should ask the user, if he/she wants to save the changing. I tried to work it out with, viewWillDissappear, but the AlterView gets displayed in the next ViewController (and program crashes, if i click on the alterViewButtons).
I'm not sure that you can change the target of a backBarButtonItem. How about self.navigationItem.leftBarButtonItem instead? There's a discussion at self.navigationItem.backBarButtonItem not working ?? Why is the previous menu still showing as the button? that may be relevant.
I have a Navigation Controller based app. From my Root VC, I have one view that I present modally like this:
[self.navigationController presentModalViewController:shortcutsViewController animated:YES];
shortcutsVC contains a row of buttons, which take the user to various places in the app.
In iOS 4.3, this works:
UINavigationController *saveNavigationController = (UINavigationController *)self.parentViewController;
[saveNavigationController pushViewController:multipleListViewController animated:YES];
[saveNavigationController dismissModalViewControllerAnimated:YES];
[multipleListViewController release];
It does not work if the dismiss happens before the push.
In iOS 5, it doesn't work at all, regardless of which order the two commands are in.
By "not work" I mean that the button highlights briefly but the new VC is not displayed.
What is the right way to do this? Or am I doing something that was illegal all along and just happened to work in 4.3?
EDIT:
I got some offline help on this one.
The problem is that in iOS5, parentViewController has been renamed presentingViewController. Since I still need to support both 4.x and 5.x, I changed this
UINavigationController *saveNavigationController = (UINavigationController *)self.parentViewController;
to this
UINavigationController *saveNavigationController;
if ([self respondsToSelector:#selector(presentingViewController)]) {
saveNavigationController = (UINavigationController *)self.presentingViewController;
} else {
saveNavigationController = (UINavigationController *)self.parentViewController;
}
And all is happy now.
I am building my first iPad application. And one of my requirements is to deal with UISplitviewcontroller and UINavigationController.our proposed view hierarchy is (LoginView) ->UINavigationView(LandingView + CollectionView)->UISplitViewcontroller( DetailsView).Our app supports only landscape mode
I am referring this SO Question( and GILT app as well), as a newbi its hard for me to get it done based on that description.
So my questions are
1) How can I achieve same thing,if somebody can give small code snippets or reference to tutorial
2) As per Apples HIG, UISplitviewcontroller should be rootviewcontroller,what if it not. Will apple reject my app.(apparently GILT group has been approved)
3) I found MGSplitViewController , can I use that one not as root?
Any help would be appreciated. As a newbi i hope my question is genuine
If you want to use the out-of the box splitView it must be root; any hokeary-pokery here will either break apples guidelines or manifest very odd behaviour.
The MGSplitViewController is completely custom implementation of a SplitViewController. Its very good if you need that sort of thing, but some of the features are based round the fact that our app will be orientating.
Alternatively you could make your own. I have done this more than once and is easier than it sounds.
(LoginView)
->UINavigationView(LandingView + CollectionView)->UISplitViewcontroller(
DetailsView).
Based on an out-of-the-box UISplitView, I would suggest:
Make the splitView the root View.
Pop (not animated) a full screen Modal as soon as the app starts and allow the
user to navigate the loginView,
LandingView and collectView in this; i also recommend using a navController here.
Once the user is ready to proceed to
the splitView, populate the
splitView's rootView Controller and
DetailViewController with whatever
you want then ,animate the Modal out.
Dave does have a point, but i would look at it from the point of view that you are removing the choice of orientation from the user; removing standard choices (like supported orientations) because the designer assumes some configuration is more efficient will only annoy some users.
I did it by making a method in my detailViewController:
-(void)popHomeScreen:(BOOL)animated//OPENS THE HOMESCREEN IN A MODAL DISPLAY
{
firstRun=NO;
//myViewControllerForPopOver init here
myViewControllerForPopOver.modalPresentationStyle = UIModalPresentationFullScreen;
myViewControllerForPopOver.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;//simple anime
if (animated) [self presentModalViewController:myViewControllerForPopOver animated:YES];
else [self presentModalViewController:myViewControllerForPopOver animated:NO];
}
Then Call it in the detailViewControllers ViewDidAppear method:
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if(firstRun)[self popHomeScreen:NO];
}
//YOU WILL ALSO NEED TO MAKE 'firstRun=YES' in viewDidLoad
//firstRun is a BOOL
As for the root disappearing (leaving a big black space)..thats a known bug. though i thought for a while that it was caused by ordering an animation while/just before it was going to draw itself.
Also, i found that if i popped a full screen modal over the splitView then popped another form based modal (for example) quickly after it the full screen modal didn't draw properly.
SplitViews are like your mother-in-law, you don't really like them and when you have to use them you have to tip-toe round the landmines.
Try this, it works for me
1) in app delegate's didFinishLaunchingWithOptions make your login view to root view
self.window.rootViewController = self.loginViewController;
also, init the split view as the template do ( but not add to self.window)
MasterViewController *masterViewController = [[[MasterViewController alloc] initWithNibName:#"MasterViewController_iPad" bundle:nil] autorelease];
UINavigationController *masterNavigationController = [[[UINavigationController alloc] initWithRootViewController:masterViewController] autorelease];
DetailViewController *detailViewController = [[[DetailViewController alloc] initWithNibName:#"DetailViewController_iPad" bundle:nil] autorelease];
UINavigationController *detailNavigationController = [[[UINavigationController alloc] initWithRootViewController:detailViewController] autorelease];
self.splitViewController = [[[UISplitViewController alloc] init] autorelease];
self.splitViewController.delegate = detailViewController;
self.splitViewController.viewControllers = [NSArray arrayWithObjects:masterNavigationController ,detailNavigationController, nil];
2) add a swap view controller in app's delegate, which swap the root view to split viewcontroller.
-(void)swapToViewControllers:(RootViewControllerType)viewType
self.window.rootViewController = self.splitViewController;
3) invoke the swapToViewControllers in your login view.
Keep in mind that the HIG strongly encourages you to support all orientations. Unless you have a very, very good reason to support landscape only, you'll probably be rejected.
See page 19 of the HIG: http://developer.apple.com/library/ios/documentation/General/Conceptual/iPadHIG/iPadHIG.pdf
Modified Ryan CY's version with storyboard.
Put this code to login controller.
1. Set storyboard id of UISplitViewController to SplitViewController;
2. Set UISplitViewController delegate and save instance
UISplitViewController* splitController = [self.storyboard instantiateViewControllerWithIdentifier:#"SplitViewController"];
UINavigationController* navigationController = [splitController.viewControllers lastObject];
splitController.delegate = (id)navigationController.topViewController;
3. Change rootViewController after login
self.view.window.rootViewController = splitController;