backBarButtonItem with popViewController and swipe - objective-c

My App logic is like that: VCA => VCB, and there is a scroll view in VCB with swipe left and right function. Some code help to understand structure, in VCB:
self.scrollView.pagingEnabled = YES;
self.scrollView.directionalLockEnabled = YES;
self.scrollView.contentSize =CGSizeMake(CGRectGetWidth(self.scrollView.frame) * numberPages, CGRectGetHeight(self.scrollView.frame));
so what I want is list some pages horizontally and swipe to left and right to navigate. Each page has it own view controller(child view controller of VCB) and I add them like that:
if (controller.view.superview == nil)
{
[self addChildViewController:controller];
[self.scrollView addSubview:controller.view];
[controller didMoveToParentViewController:self];
}
So far it works fine for iOS 6. I can swipe to change page. All function inside each page also works fine.
Then the problem comes with iOS 7's new feature, swipe to right to automatically call popViewControllerAnimated:, same effect like click go back button. To solve the conflict, I disable the interactivePopGestureRecognizer: self.navigationController.interactivePopGestureRecognizer.enabled = NO;
and it works ok, no force to pop back when I just want to swipe change the page.
Now the real problem. I set a back button(backBarButtonItem) on navigation bar. Every time I use that button pop from VCB back to VCA and current page is not the first page (that means there is at least one page on the left side), the pop animation is like first change page to the left side one, then immediately show VCA without any animation.
So any solution? Please help me.

First of all, it is hard to determine the problem without any piece of your code.
And secondly, why won't you create the button yourself, and add a target to it, a function that'll dismiss / pop the view controller?

Related

iOS 8 - Modal in Popover

I have a popover with TabBarController in it. In one tab there is a TableViewController with a list of names. And there is a plus button, that has a modal segue to AddCharacterVC for adding new names.
In iOS 7 I do it like this:
AddCharacterViewController *acvc = (AddCharacterViewController *)segue.destinationViewController;
acvc.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
acvc.modalPresentationStyle = UIModalPresentationCurrentContext;// so it does not take full screen in popover
And in AddCharacterVC I set content size like this:
- (void)viewWillAppear:(BOOL)animated {
CGSize size = CGSizeMake(320, 480); // size of view in popover
if (IDIOM == IPAD && [self respondsToSelector:#selector(preferredContentSize)]){
self.preferredContentSize = size;
}
And it works perfectly.
However, in iOS 8 modal view does not cover the whole popover, leaving TabBar visible. The user can tap on it or not, anyway modal view won't unwind properly.
I've tried:
setting acvc.modalPresentationStyle to UIModalPresentationOverCurrentContext
tried to set TabBar hidden
checked in storyboard that edges of TableVC extend under Bottom Bar and Bottom Bar in Modal View (AddCharacterVC) is set to none
All with no results.
Now the only thing I can think of is to try making modalPresentationStyleCustom and use UIPresentationController (I'm trying to do it now, but I haven't done it before). Am I missing something? Could there be other way to do it? Sorry, I cannot post images here yet. Many thanks in advance!
Ok, so I've set the modalPresentationStile to UIModalPresentationCustom, and used UIPresentationController - I've just copied code from WWDC-14's LookInside project and modified it a bit.
I'm not sure if it was the best solution, but it worked in my case.

iOS 8 UINavigationController disable Back Button

in my Navigation Controller I need to temporarily disable the back button. I know that it can be hidden using the following or something similar:
[self.navigationController.navigationItem setHidesBackButton:YES animated:YES];
But that is not what I need, instead I want the back button to be greyed out and non-responsive to user touch events. Is their a way to achieve this without replacing the default back button?
Thanks in advance!
To disable the back button, these commands would make it do what you want it to do:
Enable:
self.navigationController.navigationBar.userInteractionEnabled = YES;
self.navigationController.navigationBar.tintColor = [UIColor blueColor];
Disabled:
self.navigationController.navigationBar.userInteractionEnabled = NO;
self.navigationController.navigationBar.tintColor = [UIColor lightGrayColor];
Update:
As of iOS 7, there's also a swipe that you'll want to disable on the UINavigationBar.
// You wrap it an 'if' statement so it doesn't crash
if ([self.navigationController respondsToSelector:#selector(interactivePopGestureRecognizer)]) {
// disable the interactivePopGestureRecognizer
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
This hides the back button, so it becomes unreachable for the user. And it disables the swipe gesture.
[self.navigationItem setHidesBackButton:YES animated:YES];
Swift:
navigationItem.setHidesBackButton(true, animated: true)
See more info in Apple's documentation.
I know this is quite old but I had this problem too.
In my case in one scenario I had to disable the back button and in another one I had to disable all navigation buttons. my solution was disabling the navigation bar in total in both scenarios:
self.navigationController.view.userInteractionEnabled = NO;
This won't show the buttons as disabled but will prevent touches.
Hope this will help
I believe that following should help:
self.navigationController.navigationItem.backBarButtonItem.enabled = NO;
UPDATE
Sorry guys, my belief didn't come true.
It seems that property backBarButtonItem is designed only for setting custom title or image for Back Button.
From documentation:
If you want to specify a custom image or title for the back button,
you can assign a custom bar button item (with your custom title or
image) to this property instead. When configuring your bar button
item, do not assign a custom view to it; the navigation item ignores
custom views in the back bar button anyway.
The default value of this property is nil.
Unfortunately I didn't find any way of disabling back button with saving its native look and behaviour, because any time when I try to set custom UIBarButtonItem into navigationItem.backBarButtonItem property - it gets updated with appropriate native back button style and it always has enabled == YES.
I think this is done by Apple for a reason because we basically shouldn't force the user to stay on a detail screen and disable him from going back.
Also, in iOS7 and later user always can use swipe-from-left-edge gesture (if you don't disable it) to go back.
The only one ugly thing that I can recommend is to create a custom UIBarButtonItem and set it into leftBarButtonItem with 'Back' title, target and selector which will pop your viewController. By default it will substitute native back button.
Then you can disable it as usual using navigationItem.leftBarButtonItem.enabled = NO.
Unfortunately it will not look and act (in case of title updating depending on available space) as native back button :(
Just set a disabled back button on the navigation item of the previous view controller. Don't try to disable your custom back button if you already had one, won't work. Just set a new one which is disabled. You can reach the previous navigation item through the UINavigationBar.backItem property.
// set disabled back button
let backButton = UIBarButtonItem(title: "Back", style: UIBarButtonItem.Style.plain, target: nil, action: nil)
backButton.isEnabled = false
navigationController?.navigationBar.backItem?.backBarButtonItem = backButton
// disable pop gesture
navigationController?.interactivePopGestureRecognizer?.isEnabled = false

UINavigationBar Back button with no text, ever

I have a requirement in a project that the UINavigationBar Back button should never have text in it, it should always just be a left arrow.
By default iOS is going to insert the title of the previous controller in there. Is there any way I can stop this from happening across the whole app?
(I know I can do this screen by screen, but I'm working on an existing app with A LOT of screens it and this would be a big job)
You can always set an image of an arrow to left bar button of navigation bar
// ADDING IMAGE TO BUTTON
UIButton *refreshButton = [UIButton buttonWithType:UIButtonTypeCustom];
[refreshButton setFrame:CGRectMake(0,0,30,30)];
[refreshButton setImage:[UIImage imageNamed:#"arrow_image.png"] forState:UIControlStateNormal];
refreshButton.userInteractionEnabled=NO;
// ASSIGNING THE BUTTON WITH IMAGE TO LEFT BAR BUTTON
UIBarButtonItem *refreshBarButton = [[[UIBarButtonItem alloc] initWithCustomView:refreshButton] autorelease];
self.navigationItem.leftBarButtonItem = refreshBarButton;
You will have to write this in each view controller in order to disable default left bar button.
You can't stop it from happening across the whole app, you'll have to set it manually in each controller. You could use a category on UIViewController and call that method in each controller, which will get you down to 1 line of code that doesn't have to change if you change your approach. Still sucks, I know. Also, you will probably have issues with Apple if you do that. We tried that in one of our apps and when I showed it to the Apple guys at WWDC '13 they flat out told me they would reject the app if I submitted it that way. YMMV

Xcode - content offset in scroller view

I have a bug I've been looking at for over two hours and still don't know why it happens.
I have a registration form on a scroller view, which scrolls down if they keyboard is in the way of the textfield (function called at Editing Did Start).
Here's the code segment where the bug happens:
CGPoint scrollerOffset = scroller.contentOffset;
UITextField *currentTextField = sender;
CGPoint textFieldOrigin = currentTextField.frame.origin;
if (scrollerOffset.y < textFieldOrigin.y) {
scrollerOffset.y = textFieldOrigin.y - currentTextField.frame.size.height;
NSLog(#"Offset: %f",scrollerOffset.y);
[scroller setContentOffset:scrollerOffset animated:YES];
}
Now here's where the fun starts.
If I have the simulator like this and click inside the Phone Nr field, NSLog shows 590.000 for scrollerOffset.y and the text field jumps all the way to the top of the scrollview, as it should, just as the image next to it shows.
BUT if I have the simulator like this and click inside the Phone Nr field, NSLog shows 590.000 again but the scrollview doesn't jump up to show the text field...
Edit: If I don't animate the scrolling, it works perfectly, only bugs out when it's animated.
Well I've found the solution after a day of thinking, so if anyone has the same problem, heres's the solution:
Solution from here: http://www.pressingquestion.com/1128098/Disable-Uiscrollview-Scrolling-When-Uitextfield-Becomes-First-Responder
Basically, iOS has an in-built scroller, which is also scrolling for you if the text field is off the screen (usually the center of the text field is off the screen, off the screen being out of view, if it's hidden by the keyboard, it's still considered to be on the screen). So I called my function, did the scrolling, then iOS did his scrolling and messed me up. So you need to disable iOS' in-built scrolling.

Problem with UISPlitViewController toolbar

I'm trying to use a toolbar in a splitviewcontroller. For some reasons that are unknown to me, the table view on the left is not resized correctly.
If I turn to portrait and open the table view from the toolbar item and then go back to landscape view, the tableview is then displayed properly. I'm not sure why this happens.
This is what I have in the RootViewController:
self.navigationController.toolbar.items = [NSArray arrayWithObjects:... nil]; // Setting these to an empty array doesn't change anything
self.navigationController.toolbarHidden = NO;
self.navigationController.toolbar.barStyle = UIBarStyleDefault;
I doubt the bug is there, but the complete source code is available on github if there's something obvious to check.
I moved the code into viewDidAppear and it now works as expected.