Back Buttons from navigation bar are overlapping , swift 4 - swift

I was trying to customize my back button according to this tutorial.
In AppDelegate,
let barButtonAppearence = UIBarButtonItem.appearance()
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
let backButton = UIImage(named: "back_arrow")
let backButtonImage = backButton?.stretchableImage(withLeftCapWidth: 0, topCapHeight: 10)
barButtonAppearence.setBackButtonBackgroundImage(backButtonImage, for: .normal, barMetrics: .default)
return true
}
And then it is conflicting with the existing one (which appeared automatically because of segue(Show).
So I need to remove the blue one.

There are two things need to accomplish what you are trying to achieve:
Changing the back button's default image to your supplied image
Removing the title from the back button item
To change back button's image:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Remember, this will change every navigation bar's back button image in your app
UINavigationBar.appearance().backIndicatorImage = #imageLiteral(resourceName: "backButton")
UINavigationBar.appearance().backIndicatorTransitionMaskImage = #imageLiteral(resourceName: "backButton")
return true
}
Note: If you don't want that all your navigation bar back button to have the supplied image, you may need to subclass UINavigationController and update its navigation bar.
Removing the title from the back button item:
We will do this by adding a method to any UIViewController through extension. Extension method will be used here so that any UIViewController can be able to have this behavior when it wants.
extension UIViewController {
func removeNavigationBarBackButtonItemTitle() {
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: UIBarButtonItem.Style.plain, target: nil, action: nil)
}
}
Now, in any push transition for VC A -> VC B you need to hide the back button's title. But you have to invoke the method removeNavigationBarBackButtonItemTitle() from VC A. Just remember this and you are good to go.
class ViewControllerA: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
removeNavigationBarBackButtonItemTitle()
}
}
You will find a demo here. The demo also has some other implementations too. But you will get what you need and what I've said above.

Have you tried replacing it this way:
UINavigationBar.appearance().backIndicatorImage = UIImage(named: "back_arrow")
UINavigationBar.appearance().backIndicatorTransitionMaskImage = UIImage(named: "back_arrow")
I have tried this on applicationDidFinishLaunching method in AppDelegate

Another alternative solution to set tint color clear. See the below-modified code of your.
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
let backButton = UIImage(named: "back_arrow")
let backButtonImage = backButton?.stretchableImage(withLeftCapWidth: 0, topCapHeight: 10)
barButtonAppearence.setBackButtonBackgroundImage(backButtonImage, for: .normal, barMetrics: .default)
barButtonAppearence.tintColor = UIColor.clear
return true
}

Related

Navigation Bar Button Not Visible

This is my modified AppDelegate func
var window: UIWindow
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let button = UIBarButtonItem(title: "Logs", style: .plain, target: self, action: #selector(logButtonTapped))
window?.rootViewController?.navigationItem.rightBarButtonItem = button
return true
}
I also added Navigation Controller before my VC as below
Even if the title is visible, the right navigation button is not visible. How can I make the navigation button visible so that I can click on it?
Plus, I get this error on console
UINavigationBar decoded as unlocked for UINavigationController, or navigationBar delegate set up incorrectly. Inconsistent configuration may cause problems.
I am not sure if I understand what you are expecting very well. But I think you need to see the navBar button on the first page of your application. Isn't it?
So instead of doing this in the AppDelegate or SceneDelegate, you can add it directly to your viewController in the viewDidLoad() method.
It will be something like this:
override func viewDidLoad() {
super.viewDidLoad()
let button = UIBarButtonItem(title: "Logs", style: .plain, target: self, action: #selector(self.logButtonTapped))
navigationItem.rightBarButtonItem = button
}
If this is not what you need, please provide more info about this

Can't push a view controller again after popping it

I want to push a view controller onto the screen when a button is pressed. It works fine the first time, but when I go back and press the same button once again, it does not push the view controller again. The same problem persists when I present the view controller in fullscreen mode. But I don't face this problem when presenting the view controller in the default mode, I am able to present and dismiss the view controller as many times as I want. Someone please help me out with my problem.
[![enter image description here][3]][3]
[![enter image description here][4]][4]
[![enter image description here][5]][5]
import UIKit
#main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let window = UIWindow(frame: UIScreen.main.bounds)
window.rootViewController = UINavigationController(rootViewController: LoginViewController())
window.makeKeyAndVisible()
self.window = window
return true
}
}
#objc func signUpButtonPressed() {
let vc = SignUpViewController()
self.navigationController?.pushViewController(vc, animated: true)
}
#objc func loginButtonPressed() {
self.navigationController?.popViewController(animated: true)
}
func configureNavigationBar() {
navigationController?.navigationBar.backgroundColor = .systemBackground
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(createButtonPressed))
title = "Sign Up"
navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.font: UIFont(name: Extensions.standardFont, size: 25)!]
navigationItem.rightBarButtonItem?.tintColor = .systemBlue
}
Please ignore the scrollview in the Sign up window, it is a work in progress and does nothing at this point in time. The Login, done and create account buttons all do the same work which is to pop the signup view controller. I am able to push the signup view controller once and pop it. But if I try to press the sign up button again, the button wouldn't even respond.
Try this in you objc func to navigate to next view controller:
#objc func signUpButtonPressedTapped() {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "SignUpViewController") as! SignUpViewController
self.navigationController?.pushViewController(vc, animated: true)
}
}

I cannot change the background color of collection view programmatically

I do not know why I cannot change the first screen programmatically. The first screen remains white even if I change the color of collection view background color. I need someone's help.
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = UIWindow()
window?.makeKeyAndVisible()
let layout = UICollectionViewFlowLayout()
let navController = UINavigationController(rootViewController: PokemonController(collectionViewLayout: layout))
window?.rootViewController = navController
return true
}
This is the code inside the Controller file. I deleted the default controller file.
class PokemonController: UICollectionViewController {
//property
//Init
override func viewDidLoad() {
super.viewDidLoad()
configureViewComponent()
}
func configureViewComponent() {
collectionView.backgroundColor = .white
navigationController?.navigationBar.barTintColor = .mainPink()
}
}
Thank you!
Did you try it like this
func configureViewComponent() {
backgroundColor = .white
navigationController?.navigationBar.barTintColor = .mainPink()
}
try this and let me know, if it works.
func configureViewComponent() {
collectionView.backgroundView?.backgroundColor = .red
navigationController?.navigationBar.barTintColor = .mainPink()
}

Self.revealViewController() returns nil

I am currently trying to get the pan gesture to reveal the controller. As of right now, my open button works, but when I add the last line, my program crashes because revealViewController is nil. Link to pod: https://github.com/John-Lluch/SWRevealViewController.
import Foundation
import UIKit
class MainViewController : UIViewController{
#IBOutlet weak var mainButton: UIView!
#IBOutlet weak var Open: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated);
mainButton.makeCircle();
Open.target = self.revealViewController()
Open.action = #selector(SWRevealViewController.revealToggle(_:));
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer());
}
}
It's likely you haven't set your SWRevealViewController to be the rootViewController. Remember to set Custom Class and Storyboard ID to be SWRevealViewController in your Identity inspector.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let rootVC = storyboard.instantiateViewController(withIdentifier: "SWRevealViewController")
self.view.window?.rootViewController = rootVC
// Cont. with your code...
}
In case you need to show a login page at the beginning, you need a function in you AppDelegate, which allows the window to update the rootViewController
func changeRootVCToSWRevealVC () {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let rootVC = storyboard.instantiateViewController(withIdentifier: "SWRevealViewController")
if let window = self.window{
window.rootViewController = rootVC
}
}
After user logged in, you can change the rooViewController to SWRevealViewController.
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
appDelegate.changeRootVCToSWRevealVC()
}
If you have a variable storing the state of the last log-in, and want to navigate directly to the Navigation Drawer menu rather than LoginViewController.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let rootVCId = isLoggedin ? "SWRevealViewController" : "LoginViewController"
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let rootVC = storyboard.instantiateViewController(withIdentifier: rootVCId)
self.view.window?.rootViewController = rootVC
// Cont. with your code...
}
I was just having this same issue and came across this post. My issue turned out to be more of an "oops!" as I missed something obvious and spent 30 minutes scratching my head on it. :facepalm:
If the accepted answer doesn't work for you, check to make sure you connected your menu property to the storyboard with an outlet.
Swift:
#IBOutlet weak var menuButton:UIBarButtonItem!
override func viewDidLoad() {
if (self.revealViewController() != nil) {
menuButton.target = self.revealViewController()
menuButton.action = #selector(SWRevealViewController.revealToggle(_:))
}
}

How to add UIView on window in app delegate in swift?

view object is not getting in addsubview bracket
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool
{
// Override point for customization after application launch.
UIApplication.sharedApplication().setStatusBarHidden(true, animated: true);
var myView = UIView(frame:CGRectMake(0, 200, 320, 100));
myView.backgroundColor = UIColor.redColor()
self.window.?.addSubview(myView)
return true
}
Try to use so if access through UIViewController
let win:UIWindow = UIApplication.sharedApplication().delegate!.window!!
win.addSubview(self)
please, do the implementation for the stack properly, like e.g. this:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
window = UIWindow(frame: UIScreen.mainScreen().bounds)
let mainViewController: MainViewController = MainViewController(nibName: "MainViewController", bundle: nil)
window!.rootViewController = mainViewController
window!.makeKeyAndVisible()
return true
}
In addition to your code,
for UIApplication Root view controller's viewDidAppear Function
add below code.
override func viewDidAppear(animated: Bool)
{
super.viewDidAppear(animated)
UIApplication.sharedApplication().delegate!.window!!.bringSubviewToFront((UIApplication.sharedApplication().delegate!.window!!.subviews[0]))
}
Hope that helps :)