Crashing when I use navigation bar - ios

I'm trying to add a navigation bar to jump from my main view to a second view but I have two problems.
First: the second view is not open at full screen. It's just floating over the first one.
Second: every time I push the back button, which I've change its text to "volver", it crashes.
I've created a function I call when I press a button in the first viewController. My code is below and as you can check I've tried with dismiss, popViewController, and popToRoot but nothing works. I've given the id "RegistroViewController" to my second view.
#IBAction func registrarse(_ sender: Any) {
if let viewController = self.storyboard?.instantiateViewController(withIdentifier: "RegistroViewController") {
viewController.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Volver", style: UIBarButtonItem.Style.plain, target: self, action: #selector(UIWebView.goBack))
let navController = UINavigationController(rootViewController: viewController)
self.present(navController, animated:true, completion: nil)
}
}
func goBack(){
//self.navigationController?.popViewController(animated: true)
dismiss(animated: true, completion: nil)
//self.navigationController?.popToRootViewController(animated: true)
}
The error is:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[eventos.AuthViewController goBack]: unrecognized selector sent to instance 0x7ff192c09a80'
terminating with uncaught exception of type NSException
CoreSimulator 732.17 - Device: iPhone 8 (5334009E-7A5B-4420-A4AD-EC91CB881356) - Runtime: iOS 14.0 (18A372) - DeviceType: iPhone 8

first you have set modelPresentationStyle of a controller it will show as full screen but will present from bottom to top if you want to change transition style I will also write
let navController = UINavigationController(rootViewController: viewController)
navController.modalPresentationStyle = .overFullScreen // show full screen
// navController.modalTransitionStyle = .crossDissolve // choose whatever
self.present(navController, animated:true, completion: nil)
second the crash is due to the selector function
UIBarButtonItem(title: "Volver", style: UIBarButtonItem.Style.plain, target: self, action: #selector(UIWebView.goBack))
the goBack function must be on RegistroViewController and you can access is
UIBarButtonItem(title: "Volver", style: UIBarButtonItem.Style.plain, target: self, action: #selector(viewController.goBack))

Related

RightBarButtonItem not showing up, when leftBarButtonItem works fine

In my app I have a push segue from HomeViewController to EditProfileViewController which should have a back button as a leftBarItem and a settings cog as a rightBarItem. The back button displays normally, but the right item is missing. These ViewControllers live happen in the MainNavigationController which has a Navigation Bar.
I tried to define the rightBarButton in ViewDidLoad of the EditProfileVC, I also tried to have a rightBarItem in the storyboard for the View controller.
let buttonItem = UIBarButtonItem(image: settingsIcon, style: .plain, target: self, action: #selector(settingsPressed))
buttonItem.tintColor = UIColor(.settingsIconTint)
navigationItem.rightBarButtonItem = buttonItem
Interestingly if I change the rightBar to a leftBar item, the back button is replaced with the settings cog and works as I expect, but I can't go back to the main page.
let buttonItem = UIBarButtonItem(image: settingsIcon, style: .plain, target: self, action: #selector(settingsPressed))
buttonItem.tintColor = UIColor(.settingsIconTint)
navigationItem.leftBarButtonItem = buttonItem
To set a rightBarButtonItem in a navigationBar,
class HomeViewController: UIViewController {
#IBAction func openEditVC(_ sender: UIButton) {
if let controller = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "EditProfileViewController") as? EditProfileViewController {
self.navigationController?.pushViewController(controller, animated: true)
}
}
}
class EditProfileViewController: UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let buttonItem = UIBarButtonItem(title: "Settings", style: .plain, target: self, action: #selector(settingsPressed))
buttonItem.tintColor = .red
navigationItem.rightBarButtonItem = buttonItem
}
#objc func settingsPressed() {
print("Setting Pressed")
}
}
In the above code I've added a UIBarButtonItem with title Settings as a rightBarButtonItem of navigationBar.
No need to configure leftBarButtonItem it not required. Back button is added by default.
Screenshot:
In case it doesn't satisfy your requirement, add a screenshot of what is expected so I can help.

How to present UI view and keep Tab bar in Swift

I can not succeed in presenting a UI view and keep the Tab bar in Swift. It does successfully present but there is no tab bar. It appears that presenting a UIView removes the tab bar. Here is my code.
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Back", style: .plain, target: self, action: #selector(goMessages))
Here is what I use.
class MessagesController: UITableViewController {
let cellId = "cellId"
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Back", style: .plain, target: self, action: #selector(goMessages))
let image = UIImage(named: "new_message_icon")
navigationItem.rightBarButtonItem = UIBarButtonItem(image: image, style: .plain, target: self, action: #selector(handleNewMessage))
checkIfUserIsLoggedIn()
tableView.register(UserCell.self, forCellReuseIdentifier: cellId)
// observeMessages()
}
#objc func goMessages() {
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let Messages = storyBoard.instantiateViewController(withIdentifier: "Messages") as! MainMSGController
self.present(Messages, animated:true, completion:nil)
You have to push the view controller inside your navigationViewController.
But if you do not have one you should embed your MessagesController inside UINavigationViewController.
(inside your Main.storyboard, select MessagesController then from menu Editor -> Embed in -> Navigation Controller)
and then:
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let Messages = storyBoard.instantiateViewController(withIdentifier: "Messages") as! MainMSGController
navigationController?.pushViewController(viewController: Messages, animated: true)
to close it you can:
navigationController?.popViewController(animated: true)
You can't present view controller and keep the tabs. You can only push the view controller if you want to do that. There are some other things required but at the first glance they seem to be implemented properly in your code.

UIBARBUTTON back action

let backButton = UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.plain, target: self, action: Selector(("HomeTabController")))
self.navigationItem.leftBarButtonItem = backButton
The above code is the creation of button in navigationController but I can create a button cannot write a specific view controller to open.
I have tried with popViewController and popToRootViewController action, need a specific code for opening a particular viewController in swift, with the help of the particular viewController storyboard id and viewcontrollername.
You need to add func name in #selctor() (Swift 4 version)
let backButton = UIBarButtonItem(title: "Back", style: .plain, target: self, action: #selector(goToViewController(_:)))
self.navigationItem.leftBarButtonItem = backButton
You need to create a func.
#objc func goToViewController(_ sender: UIBarButtonItem) {
//write code here to open a view controller
let storyboard = "Main"
let viewControllerIdentifier = "HomeVC"
let viewController = UIStoryboard(name: storyboard, bundle: nil).instantiateViewController(withIdentifier: viewControllerIdentifier) as! HomeVC
//push/present "viewController"
}
in this code just replace ChatVC name to your viewcontroller name
#objc func goToViewController(_ sender: UIBarButtonItem) {
for controller in self.navigationController!.viewControllers as Array {
if controller.isKind(of: ChatVC.self) {
self.navigationController!.popToViewController(controller, animated: true)
break
} else {
self.navigationController?.popViewController(animated: true)
}
}
}

Back button suddenly stopped appearing in navigation bar

I built a simple 'About' page for my app that is simply a webView with local HTML. My Settings are contained within a separate storyboard and the AboutViewController is a view within that storyboard.
When the AboutViewController is presented it no longer shows a back button to go back to the settings.
This has worked perfectly fine for the past two weeks and has suddenly stopped working today. Is there a better way to push the view onto the navigation controller?
let storyboard = UIStoryboard(name: "Settings", bundle: nil)
let aboutViewController = storyboard.instantiateViewControllerWithIdentifier("AboutViewController") as! AboutViewController
self.navigationController?.pushViewController(aboutViewController, animated: true)
self.tableView.deselectRowAtIndexPath(indexPath, animated: true)
I have a slightly older version of my app running on my phone and it looks like this:
And now it looks like this:
Well a workaround is to put it back yourself.
override func viewWillAppear(animated: Bool)
{
super.viewWillAppear(animated)
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "< Back", style: UIBarButtonItemStyle.Plain, target: self, action: "back")
}
func back()
{
navigationController?.popViewControllerAnimated(true)
}

Add a "Done" button to dismiss a programmatically created UIViewController

I'm a swift newbie and made a demo app which has a UIViewController and UITableViewController in the Storyboard. The UIViewController has a Collection View and an embedded navigation controller. On tapping a collection view cell, the app segues to the UITableViewController. I can come back to my UIViewController from the UITableViewController as well. All this works well. Now, some of the rows in my UITableViewController have URLs. On tapping a URL, I programmatically create a webview inside a UIviewcontroller and get the URL to load in it. The issue is that I can't dismiss the webview and get back to my UITableViewController after this. This is the code I have in my UITableViewController class :
// When user taps a row, get the URL and load it in a webview
let mywebViewController = UIViewController()
let webView = UIWebView(frame: mywebViewController.view.bounds)
webView.loadRequest(NSURLRequest(URL: url)) // url from the row a user taps
mywebViewController.view = webView
self.navigationController!.presentViewController(mywebViewController, animated: true, completion: nil)
How can I add a Done button to this programmatically created UIviewcontroller to dismiss the webview and get back to my UITableViewController
You can wrap the mywebViewController in a UINavigationController then set the rightBarButtonItem to UIBarButtonItem(barButtonSystemItem: .Done, target: self, action: "dismiss") like this:
let navController = UINavigationController(rootViewController: mywebViewController)
mywebViewController.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Done, target: self, action: "dismiss")
self.navigationController!.presentViewController(navController, animated: true, completion: nil)
and add a dismiss function in your UITableViewController:
func dismiss() {
self.dismissViewControllerAnimated(true, completion: nil)
}
Add done button to your presented ViewController and make an action for it.
To dismiss ViewController try this :
self.dismissViewControllerAnimated(true, completion: nil)
You can do one thing.
As you are pushing your mywebViewController into the navigation controller, make the navigation bar visible.
By simply tapping on Back button in the navigation bar you can easily dismiss your mywebViewController.
Hope this helps you. :)
Add button in mywebViewController and in its #IBAction, call
self.dismissViewControllerAnimated(true, completion: nil)
Update for Swift 4 & 5
In the VC you're navigating from
navController.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(self.dismiss))
Have to declare your selector as an #objc func
#objc func dismiss(){
self.dismiss(animated: true)
}

Resources