Stripe iOS change back button title - ios

There's a way to change the Stripe cancel button title?
I need to change it to "Back", in fact, "Back" is a better word to describe its behavior.
I am presenting the controller of this way:
let customerContext = STPCustomerContext(keyProvider: StripeClient.shared)
let paymentMethodsViewController = STPPaymentMethodsViewController(configuration: STPPaymentConfiguration.shared(), theme: STPTheme.default(), customerContext: customerContext, delegate: self as STPPaymentMethodsViewControllerDelegate)
let navigationController = UINavigationController(rootViewController: paymentMethodsViewController)
present(navigationController, animated: true)

Go to STPCoreViewController.m in stripe files.
Just Replace this Method
- (void)commonInitWithTheme:(STPTheme *)theme {
_theme = theme;
if (![self useSystemBackButton]) {
self.cancelItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
target:self
action:#selector(handleCancelTapped:)];
self.stp_navigationItemProxy.leftBarButtonItem = self.cancelItem;
}
}
With
- (void)commonInitWithTheme:(STPTheme *)theme {
_theme = theme;
if (![self useSystemBackButton]) {
self.cancelItem = [[UIBarButtonItem alloc]
initWithTitle:#"Back"
style: UIBarButtonItemStylePlain
target:self
action:#selector(handleCancelTapped:)];
self.stp_navigationItemProxy.leftBarButtonItem = self.cancelItem;
}
}

override func pushViewController(_ viewController: UIViewController, animated: Bool) {
// first
let backItem = UIBarButtonItem()
backItem.title = "Back"
self.viewControllers.last?.navigationItem.backBarButtonItem = backItem
// then
super.pushViewController(viewController, animated: animated)
}

Related

UIPopoverPresentationController on iPhone with iOS 10

I'm trying to display a ViewController as a popover on an iPhone. I have already been through several answers on SO and the rest of the web but none have worked so far. I wrote a simple app to test this.
ViewController.swift:
import UIKit
class ViewController: UIViewController, UIPopoverPresentationControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(clicked(_:)))
}
func clicked(_ sender: Any) {
let vc = UIViewController()
vc.view.backgroundColor = UIColor.blue
vc.preferredContentSize = CGSize(width: 200, height: 200)
vc.modalPresentationStyle = .popover
present(vc, animated: true, completion: nil)
let ppc = vc.popoverPresentationController
ppc?.permittedArrowDirections = .any
ppc?.delegate = self
ppc?.barButtonItem = navigationItem.rightBarButtonItem
}
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
return .none
}
func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
return .none
}
}
The storyboard has an empty ViewController embedded in a NavigationController.
Running this, I expected a popover view controller to show under the "done" button. Instead, the blue view controller is presented full screen.
Is there a way to change this behaviour?
You are connecting delegate after presenting view. How it will return .none from delegate and show as popover. Use this :-
func clicked(_ sender: Any) {
let vc = UIViewController()
vc.view.backgroundColor = UIColor.blue
vc.modalPresentationStyle = .popover
vc.preferredContentSize = CGSize(width: 200, height: 200)
let ppc = vc.popoverPresentationController
ppc?.permittedArrowDirections = .any
ppc?.delegate = self
ppc?.barButtonItem = navigationItem.rightBarButtonItem
ppc?.sourceView = sender
present(vc, animated: true, completion: nil)
}
import UIKit
class ViewController: UIViewController, UIPopoverPresentationControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(clicked(_:)))
}
func clicked(_ sender: Any) {
let vc = UIViewController()
vc.view.backgroundColor = UIColor.blue
vc.preferredContentSize = CGSize(width: 200, height: 200)
vc.modalPresentationStyle = .popover
let ppc = vc.popoverPresentationController
ppc?.permittedArrowDirections = .any
ppc?.delegate = self
ppc!.sourceView = sender as? UIView
ppc?.barButtonItem = navigationItem.rightBarButtonItem
present(vc, animated: true, completion: nil)
}
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
return .none
}
}
The solutions above no longer work in recent iOS versions 12 and above. To get it working again, override -modalPresentationStyle within the viewController to be presented as a popover and return UIModalPresentationPopover.
Additionally provide a popoverPresentationController.delegate, implement adaptivePresentationStyleForPresentationController:traitCollection: and return UIModalPresentationNone.
#interface PopoverViewController : UIViewController
#end
#implementation PopoverViewController
- (UIModalPresentationStyle)modalPresentationStyle
{
return UIModalPresentationPopover;
}
#end
#interface ViewController ()<UIPopoverPresentationControllerDelegate>
#end
#implementation ViewController
- (IBAction)openPopover:(id)sender
{
UIViewController* testVC = [[PopoverViewController alloc] init];
testVC.view.backgroundColor = UIColor.yellowColor;
UIPopoverPresentationController* popPresenter = [testVC popoverPresentationController];
popPresenter.permittedArrowDirections = UIPopoverArrowDirectionUp;
popPresenter.delegate = self;
popPresenter.sourceView = sender;
popPresenter.sourceRect = [sender bounds];
[self presentViewController:testVC animated:YES completion:^{}];
}
#pragma mark protocol (UIPopoverPresentationControllerDelegate)
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller traitCollection:(UITraitCollection *)traitCollection
{
return UIModalPresentationNone;
}
#end
Add:
vc.popoverPresentationController?.delegate = self
just before the line:
present(vc, animated: true, completion: nil)

Swift custom back button in EKEventViewController navigation bar

I have using EKEventViewController in our app.
Code should like below
class MyEkEventViewController: EKEventViewController {
override func viewDidLoad() {
super.viewDidLoad()
let cancelButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.cancel, target: self, action: #selector(MyEkEventViewController.cancel))
self.navigationController?.navigationItem.setLeftBarButton(cancelButton, animated: false)
//self.navigationController?.navigationItem.leftBarButtonItem = cancelButton
}
}
#objc fileprivate func cancel() {
_ = navigationController?.popViewController(animated: true)
}
}
# My invocation
.
.
.
let eventViewController = MyEkEventViewController()
eventViewController.delegate = self
eventViewController.allowsEditing = true
eventViewController.allowsCalendarPreview = true
eventViewController.hidesBottomBarWhenPushed = true
eventViewController.event = event
self.navigationController?.pushViewController(eventViewController, animated: true)
Back arrow only displayed. But Cancel button is not displayed in left side navigation bar.

Swift - Help Converting from Objective C Syntax

I'm trying to replace the UINavigationController BackBarButtonItem with a custom image, and I would like there to be no back icon like it's currently doing here:
I'm taking this picture from another stack post, but something similar is happening with mine
The solution to this was listed here: Remove back arrow in iOS7
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"back-btn"]
style:UIBarButtonItemStylePlain
target:nil
action:nil];
if ([UINavigationBar instancesRespondToSelector:#selector(setBackIndicatorImage:)]) {
[[UINavigationBar appearance] setBackIndicatorImage:[[UIImage alloc] init]];
[[UINavigationBar appearance] setBackIndicatorTransitionMaskImage:[[UIImage alloc] init]];
}
The problem is I'm having trouble converting this code to Swift. If anybody could help me that would be greatly appreciated. Thanks in advance!
For getting swipe back feature :
First set delegate in viewDidLoad:
self.navigationController!.interactivePopGestureRecognizer.delegate = self
And then disable gesture when pushing:
override func pushViewController(_ viewController: UIViewController, animated: Bool) {
super.pushViewController(viewController, animated: animated)
self.interactivePopGestureRecognizer.isEnabled = false
}
And enable in viewDidDisappear:
self.navigationController!.interactivePopGestureRecognizer.isEnabled = true
Use below code:
//Hide Default Back Button First
self.navigationItem.setHidesBackButton(true, animated:true);
//Your code to show back button
let backButton = UIButton()
backButton.setImage(UIImage(named: "imagename"), forState: .Normal)
backButton.frame = CGRectMake(0, 0, 30, 30)
backButton.addTarget(self, action: Selector("action"), forControlEvents: .TouchUpInside)
let rightBarButton = UIBarButtonItem()
rightBarButton.customView = backButton
self.navigationItem.leftBarButtonItem = rightBarButton
//Back Button Action
func action()
{
self.navigationController?.popViewControllerAnimated(true)
}
Or you can refer one of the answer
Use following code in swift 2.2 (xocde 7.3) :
class BaseViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.setBackButton()
}
func setBackButton() {
let backImage = UIImage(named:"back_icon") as UIImage!
let backButton = UIBarButtonItem(image: backImage, style:UIBarButtonItemStyle.Plain, target: self, action: #selector(BaseViewController.viewWillDisappearC) )
self.navigationItem.leftBarButtonItem = backButton
}
func viewWillDisappearC() {
self.navigationController?.popViewControllerAnimated(true)
}
}
Use following code in swift 3 :
class BaseViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.setBackButton()
}
func setBackButton() {
let backImage = UIImage(named:"back_icon") as UIImage!
let backButton = UIBarButtonItem(image: backImage, style: UIBarButtonItemStyle.plain, target: self, action: #selector(BaseViewController.viewWillDisappearC) )
self.navigationItem.leftBarButtonItem = backButton
}
func viewWillDisappearC() {
_ = self.navigationController?.popViewController(animated: true)
}
}

Unable to display Toolbar items in a NavigationController using Swift

I am trying to display toolbar items at the bottom of TableViewController which is inside a Navigation Controller. I’ve written this code in Swift.
I've used Xcode default master-detail template to create the project and written the below code in ViewDidLoad method of MasterTableViewController.
Please help me to fix the issue.
Please find below code snippet.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.addToolBar();
}
func addToolBar ()->Void {
self.hidesBottomBarWhenPushed = false
var toolBarItems = NSMutableArray()
var systemButton1 = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Play, target: nil, action: nil)
toolBarItems.addObject(systemButton1)
var systemButton2 = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
toolBarItems.addObject(systemButton2)
var systemButton3 = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Trash, target: nil, action: nil)
toolBarItems.addObject(systemButton3)
self.navigationController?.toolbarHidden = false
self.setToolbarItems(toolbarItems, animated: true)
//self.navigationController?.toolbarItems = toolbarItems;
}
But Interestingly, the same code written in Objective-C works and shows the toolbar at the bottom with two items
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.navigationItem.leftBarButtonItem = self.editButtonItem;
[self addToolbar];
}
-(void) addToolbar
{
self.hidesBottomBarWhenPushed = NO;
NSMutableArray *items = [[NSMutableArray alloc] init];
UIBarButtonItem *item1 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemPlay target:nil action:nil];
[items addObject:item1];
UIBarButtonItem *item2 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
[items addObject:item2];
UIBarButtonItem *item3 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemTrash target:nil action:nil];
[items addObject:item3];
self.navigationController.toolbarHidden = NO;
// self.navigationController.toolbarItems = items;
//
[self setToolbarItems:items animated:YES];
}
You have a tiny typo in your code. I highlighted the difference for you:
var toolBarItems = NSMutableArray()
// ^
// [...]
self.setToolbarItems(toolbarItems, animated: true)
// ^
Your code does basically this (with an animation):
self.toolbarItems = self.toolbarItems
Your set the toolbarItems array to the current toolbarItems array, which is empty.
when you use self.setToolbarItems(toolBarItems, animated: true) it will work.
Using NSMutableArray gave me error, the below code worked for me
func setUpToolbar(){
var toolBarItems = [UIBarButtonItem]()
let systemButton1 = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Play, target: nil, action: nil)
toolBarItems.append(systemButton1)
let systemButton2 = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
toolBarItems.append(systemButton2)
let systemButton3 = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Trash, target: nil, action: nil)
toolBarItems.append(systemButton3)
self.setToolbarItems(toolBarItems, animated: true)
self.navigationController?.toolbarHidden = false
}

Change UINavigationBar back button title

In my application I want to use 'Back' text as back button title for every viewcontroller.
I have read so many posts on stackoverflow but got nothing.
I don't want to set leftbarbuttonitem.
Can anyone help me on this simple task.
Thanks,
Do this in the parent view controller not in the child
Swift
navigationItem.backBarButtonItem = UIBarButtonItem(title: "Back", style: .plain, target: nil, action: nil)
Objetive-C
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:nil action:nil];
self.navigationController.navigationBar.topItem.title = #"";
If you are using storyboard you can select the navigation item in the parent view controller and set the button text you want in 'Back Button' field. Remember to set this in the parent view controller, not in the child that is pushed.
Try this hope it will be work
UIBarButtonItem *btn =
[[UIBarButtonItem alloc] initWithTitle:#"New Title"
style:UIBarButtonItemStyleBordered
target:nil
action:nil];
[[self navigationItem] setBackBarButtonItem:btn];
I needed to use self.navigationController.navigationBar.backItem.title = #"";, the difference being that I'm using backItem instead of topItem.
Back Button With Back Arrow
Objective-C
self.navigationController.navigationBar.topItem.backBarButtonItem =
[[UIBarButtonItem alloc] initWithTitle:#"Title" style:UIBarButtonItemStylePlain
target:nil action:nil];
Swift
self.navigationController?.navigationItem.backBarButtonItem =
UIBarButtonItem(title:"Title", style:.plain, target:nil, action:nil)
Normal Button Without Back Arrow
Objective-C
self.navigationItem.leftBarButtonItem =
[[UIBarButtonItem alloc] initWithTitle:#"Title"
style:UIBarButtonItemStylePlain target:nil action:nil];
Swift
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title:"Title",
style:.plain, target:nil, action:nil)
Bold Button Without Back Arrow
Objective-C
self.navigationItem.leftBarButtonItem =
[[UIBarButtonItem alloc] initWithTitle:#"Title"
style:UIBarButtonItemStyleDone target:nil action:nil];
Swift
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title:"Title",
style:.done, target:nil, action:nil)
navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
Changes the currently visible Back Button
extension UIViewController {
func setCurrentBackButton(title: String) {
guard let vcCount = self.navigationController?.viewControllers.count else {
return
}
let priorVCPosition = vcCount - 2
guard priorVCPosition >= 0 else {
return
}
self.navigationController?.viewControllers[priorVCPosition].navigationItem.backBarButtonItem = UIBarButtonItem(title: title, style: .plain, target: self, action: nil)
}
swift 2.0:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.navigationBar.topItem?.title = ""
}
Note: It works only if storyboard have a chain of navigation stack.
Other options/changing title:
self.navigationController?.navigationBar.backItem?.title = ""
navigationItem.backBarButtonItem?.title = ""
navigationItem.leftBarButtonItem?.title = ""
Removing navigationItem:
navigationItem.setLeftBarButtonItem(nil, animated: true)
To remove back button title for all view controller add new swift file and copy this extinction to it
import UIKit
extension UIViewController {
static func swizzle(){
let orginalSelector = #selector(viewDidLoad)
let swizzledSelector = #selector(swizzledViewDidLoad)
let orginalMethod = class_getInstanceMethod(UIViewController.self, orginalSelector)
let swizzledMethod = class_getInstanceMethod(UIViewController.self, #selector(swizzledViewDidLoad))
let didAddMethod = class_addMethod(UIViewController.self, orginalSelector, method_getImplementation(swizzledMethod!), method_getTypeEncoding(swizzledMethod!))
if didAddMethod {
class_replaceMethod(UIViewController.self, swizzledSelector, method_getImplementation(orginalMethod!), method_getTypeEncoding(orginalMethod!))
}else{
method_exchangeImplementations(orginalMethod!, swizzledMethod!)
}
}
#objc func swizzledViewDidLoad(){
navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
swizzledViewDidLoad()
}
}
After that in AppDelegate inside didFinishLaunchingWithOptions, call the swizzle function.
UIViewController.swizzle()
This function is using the objective c runtime to exchange the viewDidLoad method with another one that removes the back button title and then inside it recall the original viewDidLoad.
in AppDelegate in the DidFinishLaunchingWithOptions add this code:
[[UIBarButtonItem appearance]
setBackButtonTitlePositionAdjustment:UIOffsetMake(-1000.0, 0.0)
forBarMetrics:UIBarMetricsDefault];

Resources