Swift 3 - Push a new view but keep the same NavigationBar - ios

I have a UISearchBar in my application. When I press a button to "open" the searchbar does a new view appear. But the problem is that the NavigationController changes and the UISearchBar disappear. How can I do so I can keep the current NavigationController with my searchbar even if a new view appear. (So I still searching when the new view appear)
P.s my code is not the best and I´m not using Storyboard!
class HomeController: UICollectionViewController, UICollectionViewDelegateFlowLayout, UISearchBarDelegate {
override func viewDidLoad() {
super.viewDidLoad()
collectionView?.backgroundColor = UIColor.white
setupNavigationBar()
}
Here is the new view that appear:
class UserSearchController: UICollectionViewController, UISearchBarDelegate {
override func viewDidLoad() {
super.viewDidLoad()
collectionView?.backgroundColor = UIColor.blue
}
}
And here is the whole searchbar code:
import UIKit
var searchBar = UISearchBar()
var searchBarButtonItem: UIBarButtonItem?
var logoImageView: UIImageView!
extension HomeController {
func setupNavigationBar() {
let button = UIButton(type: .system)
button.setImage(#imageLiteral(resourceName: "search"), for: .normal)
button.addTarget(self, action: #selector(showSearchBar), for: .touchUpInside)
button.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
let barButton = UIBarButtonItem(customView: button)
self.navigationItem.rightBarButtonItem = barButton
let logoImage = UIImage(named: "home")!
logoImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: logoImage.size.width, height: logoImage.size.height))
logoImageView.image = logoImage
navigationItem.titleView = logoImageView
searchBar.delegate = self
searchBar.searchBarStyle = UISearchBarStyle.minimal
searchBar.placeholder = "Search"
searchBar.barTintColor = UIColor.gray
searchBarButtonItem = navigationItem.rightBarButtonItem
}
func showSearchBar() {
let layout = UICollectionViewFlowLayout()
let userSearchController = UserSearchController(collectionViewLayout: layout)
self.navigationController?.pushViewController(userSearchController, animated: true)
searchBar.alpha = 0
navigationItem.titleView = searchBar
navigationItem.setLeftBarButton(nil, animated: true)
navigationItem.rightBarButtonItem = nil
searchBar.showsCancelButton = true
UIView.animate(withDuration: 0.5, animations: {
self.searchBar.alpha = 1
}, completion: { finished in
self.searchBar.becomeFirstResponder()
})
}
public func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
hideSearchBar()
}
func hideSearchBar() {
navigationItem.setRightBarButton(searchBarButtonItem, animated: true)
logoImageView.alpha = 0
UIView.animate(withDuration: 0.3, animations: {
self.navigationItem.titleView = self.logoImageView
self.logoImageView.alpha = 1
}, completion: { finished in
})
}
}

The reason why your search bar is only visible on your first View Controller is because you are using the View Controller's titleView property. Each UIViewController has it's own titleView property, so if you push a View Controller onto your first VC, it will also need to have the titleView property set to a search bar view with the required configuration.

I think you can create a base class, add UISearchBar above the base class, and then you want the current controller with UISearchBar to inherit your base class

Related

currentContext presentation style changes the size of the child view controller's view

I have a parent view controller and a child view controller that takes up a portion of the parent's main view:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let childVC = ChildVC()
addChild(childVC)
childVC.view.frame = CGRect(origin: CGPoint(x: 100, y: 100), size: CGSize(width: 200, height: 200))
view.addSubview(childVC.view)
childVC.didMove(toParent: self)
}
}
class ChildVC: UIViewController {
override func loadView() {
let v = UIView()
v.backgroundColor = .cyan
view = v
}
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(type: .system)
button.setTitle("Present", for: .normal)
button.addTarget(self, action: #selector(pressed), for: .touchUpInside)
button.sizeToFit()
view.addSubview(button)
}
#objc func pressed() {
self.definesPresentationContext = true
self.providesPresentationContextTransitionStyle = true
self.modalTransitionStyle = .crossDissolve
let pvc = PresentedVC()
pvc.modalPresentationStyle = .currentContext
self.present(pvc, animated: true, completion: nil)
}
}
class PresentedVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .yellow
let button = UIButton(type: .system)
button.setTitle("Dismiss", for: .normal)
button.addTarget(self, action: #selector(pressed), for: .touchUpInside)
button.sizeToFit()
view.addSubview(button)
}
#objc func pressed() {
self.dismiss(animated: true, completion: nil)
}
}
When I present a view controller using the currentContext style, it presents the new view controller as it should, covering only the child view controller's view:
However, when I dismiss it, the size of the ChildVC's main view takes up the entire screen:
When I log the superview of the ChildVC's main view, it's still a subview of the parent view controller's main view so I'm not sure why this is happening.
Just change your presentationStyle to .overCurrentContext like this:
#objc func pressed() {
self.definesPresentationContext = true
self.providesPresentationContextTransitionStyle = true
self.modalTransitionStyle = .crossDissolve
let pvc = PresentedVC()
pvc.modalPresentationStyle = .overCurrentContext // <-- here
pvc.modalTransitionStyle = .crossDissolve // <-- and here
self.present(pvc, animated: true, completion: nil)
}
It will prevent the unwanted upscaling.

rightBarButtonItem appearing in the middle

The rightbarbuttonitem is not appearing on the right side of the navigation bar. I want the navigation bar to look similar to the one in the "App Store"
I have tried doing this in the storyboard and in the code, setting the image content mode, clipping to bounds, and giving it a frame.
I have also been looking at solutions online and none of them have worked for me. Any help or suggestions would be appreciated, thanks.
Here are some screenshots:
import UIKit
class KYSearchBarController: UISearchController {
override init(searchResultsController: UIViewController?) {
super.init(searchResultsController: searchResultsController)
}
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
// Call in view did appear
func CustomizeSearchBar() {
// Changing color of text in textfield.
let textfieldInsideBar = self.searchBar.value(forKey: "searchField") as? UITextField
textfieldInsideBar?.textColor = .darkGray
// Chaning placeholder
let textfieldLbl = textfieldInsideBar?.value(forKey: "placeholderLabel") as? UILabel
textfieldLbl?.textColor = .darkGray
textfieldLbl?.textAlignment = .center
// Icon customization
let glassIcon = textfieldInsideBar?.leftView as? UIImageView
glassIcon?.image = #imageLiteral(resourceName: "icon")
glassIcon?.image?.withRenderingMode(.alwaysTemplate)
glassIcon?.tintColor = .darkGray
// Centering textfield text
textfieldInsideBar?.textAlignment = .center
let clearButton = textfieldInsideBar?.value(forKey: "clearButton") as! UIButton
clearButton.setImage(UIImage(named: "icon1"), for: .normal)
clearButton.tintColor = .darkGray
}
}
extension UIView {
func MakeRound() {
self.layer.cornerRadius = self.frame.width / 5.0
}
}
class ViewController: UIViewController, UISearchBarDelegate {
let searchController = KYSearchBarController(searchResultsController: nil)
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.searchController = searchController
navigationItem.hidesSearchBarWhenScrolling = false
let userimage = UIImageView(image: UIImage(named: "person1"))
userimage.frame = CGRect(x: 60, y: 0, width: 50, height: 50)
userimage.clipsToBounds = true
userimage.layer.masksToBounds = true
userimage.contentMode = .scaleAspectFit
userimage.MakeRound()
let rightBarButton = UIBarButtonItem(customView: userimage)
navigationItem.rightBarButtonItem = rightBarButton
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
searchController.CustomizeSearchBar()
}
}
Add the userimage property to make it accessible inside the ViewController.
class ViewController: UIViewController, UISearchBarDelegate {
let searchController = KYSearchBarController(searchResultsController: nil)
let userimage = UIImageView(image: UIImage(named: "person1"))
}
Add the makeRound() function call to viewWillLayoutSubviews().
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
userimage.makeRound()
}
Update the makeRound() function to make a circle.
extension UIView {
func makeRound() {
self.layer.cornerRadius = self.frame.width / 2.0
}
}
Add a method to add the necessary constraints.
func setupConstraints() {
navigationItem.searchController = searchController
navigationItem.hidesSearchBarWhenScrolling = false
guard let navigationBar = self.navigationController?.navigationBar else { return }
navigationBar.addSubview(userimage)
userimage.clipsToBounds = true
userimage.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
userimage.rightAnchor.constraint(equalTo: navigationBar.rightAnchor, constant: -16),
userimage.bottomAnchor.constraint(equalTo: navigationBar.bottomAnchor, constant: -12),
userimage.heightAnchor.constraint(equalToConstant: 40),
userimage.widthAnchor.constraint(equalTo: userimage.heightAnchor)
])
}
Setup a gesture recognizer for the UIImageView and implementation for it.
func setUpGestureRecognizer() {
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(profile))
userimage.isUserInteractionEnabled = true
userimage.addGestureRecognizer(tapGestureRecognizer)
}
#objc func profile() {
// Your implementation
}
Update viewDidLoad() with the method call.
override func viewDidLoad() {
super.viewDidLoad()
// Setup constraints
setupConstraints()
setUpGestureRecognizer()
}
I ran into the same issue when I was using a very large image for my UIBarButtonItem.
Once I resized my image to a smaller size, it was appropriately placed at the right hand side of the navigation bar. It looks like you are having the same issue.
Alternatively, since starting from iOS 11 navigation bar uses autolayout, replacing the line
userimage.frame = CGRect(x: 60, y: 0, width: 50, height: 50)
with the below should also do the trick:
userimage.widthAnchor.constraint(equalToConstant: 50).isActive = true
userimage.heightAnchor.constraint(equalToConstant: 50).isActive = true

How to add a segmented control to a navigation bar ? (iOS)

I would like to add a segmented control to a navigation bar like this
but when i drag the segmented control to the navigation bar the large title is gone. How can create the above UI ?
You should add the segmented control as the titleView of the navigation bar.
Below is the sample code:
let titles = ["All", "Missed"]
segmentControl = UISegmentedControl(items: titles)
segmentControl.tintColor = UIColor.white
segmentControl.backgroundColor = UIColor.blue
segmentControl.selectedSegmentIndex = 0
for index in 0...titles.count-1 {
segmentControl.setWidth(120, forSegmentAt: index)
}
segmentControl.sizeToFit()
segmentControl.addTarget(self, action: #selector(segmentChanged), for: .valueChanged)
segmentControl.selectedSegmentIndex = 0
segmentControl.sendActions(for: .valueChanged)
navigationItem.titleView = segmentControl
You can try the below simple code,
var segmentedController: UISegmentedControl!
let items = ["Label A", "Label B"]
segmentedController = UISegmentedControl(items: items)
navigationItem.titleView = segmentedController
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Edit", style: .plain, target: self, action: #selector(handleSignOut))
navigationItem.rightBarButtonItem?.tintColor = UIColor.black
If you want to add UISegmentControl by using XIB then you can do that by following these simple steps:
Design your custom view in XIB (Refer XIB for your reference https://i.stack.imgur.com/AJDCo.png)
Put the code in your ViewController
class ViewController: UIViewController {
lazy var navSegmentedView: YourCustomView = {
guard let aView = Bundle.main.loadNibNamed("\(YourCustomView.self)", owner: self, options: nil)?.first as? YourCustomView else { return YourCustomView() }
aView.backgroundColor = .clear
aView.frame = CGRect(x: 0, y: 0, width: 160, height: 40)
aView.segmentControl.addTarget(self, action: #selector(segmentChanged(_:)), for: .valueChanged)
return aView
}()
override func viewDidLoad() {
super.viewDidLoad()
setupNavBar()
}
func setupNavBar() {
navigationItem.titleView = navSegmentedView
navigationItem.titleView?.backgroundColor = .clear
}
#objc func segmentChanged(_ sender: UISegmentedControl) {
print(sender.selectedSegmentIndex)
}
}

Show back button without navigation view controller

I have the scheme: UITabBarViewController (with 3 tabs).
In all that tabs I don't want to show navigation menu on top.
And from the first tab, I want to push another view controller from button click that will have "back" button (and top toolbar with "cancel")
I tried some ways - in storyboard with push segue - no back button.
Probably because i don't have navigation view controller, so my navigation stack is empty.
Programmatically:
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewController(withIdentifier: "AddCoinTableViewController") as! AddCoinTableViewController
self.present(nextViewController, animated:true, completion:nil)
If I embed tabs in navigation controller, then I have top toolbar (which I don't want).
Any ideas how to make it?
You can't achieve navigation functionality without using UINavigationController. I mean you have to do all animation kind of stuff on your own, and I think that's not a good idea. Rather than that, you can use UINavigationController, and if you don't want to show navigationBar at some viewController, than do as follows for those view controllers.
override func viewWillApear() {
super.viewDidLoad()
self.navigationController?.isNavigationBarHidden = true
}
override func viewWillDisappear(animated: Bool) {
self.navigationController?.isNavigationBarHidden = false
}
You can embed the navigation controller at your first tab controller (or any you want), and hide it at the controllers you don't want on their viewDidLoad like this:
self.navigationController?.isNavigationBarHidden = true
Doing this, you will be able to see the back Button at the controllers you pushed and didn't hide the navigationBar.
Make sure you push the controller using the navigation controller like this:
self.navigationController?.pushViewController(YOUR VIEW CONTROLLER, animated: true)
The below code will allow you to create your own Navigation handling class and have the "push" "pop" animation that UINavigationController has.. You can create a new project, copy paste the below into ViewController.swift and see for yourself..
Now you can give any UIViewController navigation controller abilities..
import UIKit
class NavigationHandler : NSObject, UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning, UINavigationBarDelegate {
private var isPresenting: Bool = false
private weak var controller: UIViewController?
init(controller: UIViewController) {
super.init()
self.controller = controller
controller.transitioningDelegate = self
let navigationBar = UINavigationBar()
controller.view.addSubview(navigationBar)
NSLayoutConstraint.activate([
navigationBar.leftAnchor.constraint(equalTo: controller.view.leftAnchor),
navigationBar.rightAnchor.constraint(equalTo: controller.view.rightAnchor),
navigationBar.topAnchor.constraint(equalTo: controller.view.safeAreaLayoutGuide.topAnchor)
])
navigationBar.translatesAutoresizingMaskIntoConstraints = false
navigationBar.delegate = self
let item = UINavigationItem(title: controller.title ?? "")
let barButton = UIBarButtonItem(title: "Back", style: .done, target: self, action: #selector(onBackButton(button:)))
item.leftBarButtonItems = [barButton]
navigationBar.setItems([item], animated: true)
}
func position(for bar: UIBarPositioning) -> UIBarPosition {
return .topAttached
}
#objc
private func onBackButton(button: UIBarButtonItem) {
self.controller?.dismiss(animated: true, completion: nil)
}
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
self.isPresenting = true;
return self;
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
self.isPresenting = false;
return self;
}
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.25;
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let duration = self.transitionDuration(using: transitionContext)
let fromController = transitionContext.viewController(forKey: .from)
let toController = transitionContext.viewController(forKey: .to)
let containerView = transitionContext.containerView
if self.isPresenting {
let frame = fromController!.view.frame
containerView.addSubview(toController!.view)
toController?.view.frame = CGRect(x: frame.origin.x + frame.width, y: frame.origin.y, width: frame.width, height: frame.height)
UIView.animate(withDuration: duration, animations: {
fromController?.view.frame = CGRect(x: frame.origin.x - frame.size.width, y: frame.origin.y, width: frame.size.width, height: frame.size.height)
toController?.view.frame = frame
}, completion: { (completed) in
transitionContext.completeTransition(true)
})
}
else {
let frame = fromController!.view.frame
containerView.insertSubview(toController!.view, at: 0)
toController?.view.frame = CGRect(x: frame.origin.x - frame.size.width, y: frame.origin.y, width: frame.size.width, height: frame.size.height)
UIView.animate(withDuration: duration, animations: {
fromController?.view.frame = CGRect(x: frame.origin.x + frame.width, y: frame.origin.y, width: frame.width, height: frame.height)
toController?.view.frame = frame
}, completion: { (completed) in
transitionContext.completeTransition(true)
})
}
}
}
View Controllers for testing:
class ViewController : UIViewController {
private var navigationHandler: NavigationHandler?
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(type: .custom)
button.setTitle("Push Controller", for: .normal)
button.setTitleColor(UIColor.red, for: .normal)
button.layer.borderColor = UIColor.black.cgColor
button.layer.borderWidth = 1.0
button.layer.cornerRadius = 5.0
button.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(button)
NSLayoutConstraint.activate([
button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
button.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
button.heightAnchor.constraint(equalToConstant: 45.0),
button.widthAnchor.constraint(equalToConstant: 150.0)
])
button.addTarget(self, action: #selector(onPush(button:)), for: .touchUpInside)
}
#objc
private func onPush(button: UIButton) {
let child = ChildViewController()
self.navigationHandler = NavigationHandler(controller: child)
self.present(child, animated: true, completion: nil)
}
}
class ChildViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.blue
}
}

Trying to call a navigation bar function in another class pragmatically

I created a navigation bar which I'm trying to call in another view controller. I set it up by calling the methods which I separated into left, center and right buttons. In my other controller I call the navbarcontroller and try and call the method for which i setup the navigation toolbar. Nothing happens, however there is no crash.
import UIKit
class NavBarController : UIViewController{
var screenSize: CGRect!
override func viewDidLoad() {
super.viewDidLoad()
setupNavigationBarItems()
setupToolBarItems()
self.navigationController?.isToolbarHidden = false
self.view!.backgroundColor = .white
}
and my method for the navigation bar is this
func setupNavigationBarItems() {
setupCenterNavButton()
setupLeftNavButton()
setupRightNavButton()
}
func showCalendarController() {
let navController = CalendarController()
self.present(navController, animated: true, completion: nil)
} //connect bottom bar buttons to controller
func showEventsController() {
let navController = EventsController()
self.present(navController, animated: true, completion: nil)
} //connect bottom bar buttons to controller
func setupNavigationBarItems() {
setupCenterNavButton()
setupLeftNavButton()
setupRightNavButton()
} // top bar button setup
private func setupCenterNavButton() {
let buttonFrame = UIView(frame: CGRect(x: 0, y: 0, width: 165,
height: 20))
mainFeedButton.frame = CGRect(x: 0,y: 0, width: 80,height: 20) as
CGRect
mainFeedButton.backgroundColor = UIColor.blue
peekFeedButton.frame = CGRect(x: 85,y: 0, width: 80,height: 20) as
CGRect
peekFeedButton.backgroundColor = UIColor.blue
buttonFrame.addSubview(mainFeedButton)
buttonFrame.addSubview(peekFeedButton)
navigationItem.titleView = buttonFrame
} //center bar buttons / action setup
private func setupLeftNavButton() {
navigationItem.leftBarButtonItem = UIBarButtonItem(customView:
favoriteButton)
}// left bar buttons / action setup
private func setupRightNavButton() {
navigationItem.rightBarButtonItem = UIBarButtonItem(customView:
moreButton)
} //right bar buttons / action setup
lazy var mainFeedButton: UIButton! = {
let button = UIButton(type: .custom) // button type
button.setTitle("Main",for: .normal) //button title
button.sizeToFit() // size button to fit the title
var frame = button.frame //create frame to manipulate the body
button.frame = CGRect(x: 0, y: 0, width: 100, height: 40)
button.addTarget(self, action:
#selector(self.showMainFeedController),
for: .touchUpInside)
return button
}() //mainFeed button connected to Feed Controller
lazy var peekFeedButton: UIButton! = {
let button = UIButton(type: .custom) //button type
button.setTitle("Spy",for: .normal) //button title
button.sizeToFit() // size button to fit the title
var frame = button.frame //create frame to manipulate the body
button.frame = CGRect(x: 20, y: 0, width: 100, height: 40)
button.addTarget(self, action:
#selector(self.showSpyFeedController),
for: .touchUpInside)
return button
}()//peekFeed button frame and action setup
lazy var favoriteButton: UIButton! = {
let button = UIButton(type: .system) //default button with blue
text
button.setImage(#imageLiteral(resourceName:
"star").withRenderingMode(.alwaysOriginal), for: .normal)
button.contentMode = .scaleAspectFit
button.frame = CGRect(x: 0, y: 0, width: 24, height: 24)
button.addTarget(self, action: #selector(favoriteButton_tapped),
for: .touchUpInside)
return button
}() //favorites button frame and action setup
lazy var moreButton: UIButton! = {
let button = UIButton(type: .system) //default button with blue
text
button.setImage(#imageLiteral(resourceName:
"more").withRenderingMode(.alwaysOriginal), for: .normal)
button.contentMode = .scaleAspectFit
button.frame = CGRect(x: 0, y: 0, width: 24, height: 24)
button.addTarget(self, action: #selector(moreButton_tapped),
for: .touchUpInside)
return button
}() //more button frame and action setup
func showMainFeedController() {
let navController = MainFeedController()
self.present(navController, animated: true, completion: nil)
} //mainFeed button connected to Feed Controller
func showSpyFeedController() {
let navController = SpyFeedController()
self.present(navController, animated: true, completion: nil)
}//peekFeed button connected to SpyFeedController
func favoriteButton_tapped(sender: UIButton) {
print("You touched this!")
}
func moreButton_tapped(sender: UIButton) {
print("You touched this!")
}
}
I then try and call the function by setupNavigationBarItems() like this
import UIKit
class EventsController: UIViewController{
override func viewDidLoad() {
super.viewDidLoad()
let navbar = NavBarController()
navbar.setupNavigationBarItems()
self.navigationController?.isToolbarHidden = false
self.view.backgroundColor = .white
}
}
I'm not sure if this a valid way. I'm still kinda new to all of this.
It's not clear what you expect to happen, but here's what does happen:
let navbar = NavBarController()
A completely new NavBarController object is created.
navbar.setupNavigationBarItems()
That NavBarController object's setupNavigationBarItems is called.
self.navigationController?.isToolbarHidden = false
self.view.backgroundColor = .white
Your code comes to an end. navbar was a local variable, so the NavBarController object vanishes in a puff of smoke. The end. This object was created and configured to no purpose.
I remember my first month in iOS way back 2015 :D, didn't have any knowledge in OOP, I didn't know too how to pass a data to another screen or class.
Anyways, you DO NOT create a new instance of your NavBarController class in your EventsController. If you want to talk to your NavBarController from your EventsController, then you will need a reference that is currently alive. You can also use delegate (search for that later).
So before you show or present your EventsController from your NavBarController, pass your current NavBarController instance to the next screen which is EventsController. BUT FIRST, you need to declare a variable in your EventsController, correct? :)
Declare a variable with a type of NavBarController inside your EventsController class, like so:
var navBarController: NavBarController!
Then in this piece of code of yours, pass your self (the NavBarController instance) to the EventsController class before showing or presenting, take note that you mistakenly gave a wrong name to your EventsController new instance, so I renamed it:
func showEventsController() {
let eventsController = EventsController()
eventsController.navBarController = self // THIS :)
self.present(eventsController, animated: true, completion: nil)
}
Lastly, instead of this:
let navbar = NavBarController()
navbar.setupNavigationBarItems()
Make use of your declared variable, like so:
self.navBarController.navbar.setupNavigationBarItems()
Hope this helps! :)

Resources