SIGABRT error on ios simulator - ios

I use viewcontrollers with Navigation Controller. I press a UIButton on homescreeen and go another viewcontroller. When I click a UIButton on new viewcontroller, I go homescreen again. But when I press a UIButton on homescreen, this time, it gives an error.
I created button with codes, not on storyboard.
What could be the problem?
Some friends say, poptorootviewcontroller solves the problem, but I dont know adding it to button.
Anyone can help?
here s a short video of it;
here is the code;
override func viewDidLoad() {
super.viewDidLoad()
let closeButton = UIButton()
closeButton.frame = CGRect(x: screen.width - 70, y: 20, width: 60, height: 60)
closeButton.setTitle("Skip", forState: .Normal)
closeButton.setTitleColor(UIColor(red: 0.0/255.0, green: 0.0/255.0, blue: 0.0/255.0, alpha: 0.5), forState: .Normal)
closeButton.titleLabel!.font = UIFont.systemFontOfSize(16)
closeButton.addTarget(self, action: #selector(OnboardingController2.pressed(_:)), forControlEvents: .TouchUpInside)
view.addSubview(closeButton)
}
func pressed(sender: UIButton!) {
audioPlayer?.stop();
let loginPageView = self.storyboard?.instantiateViewControllerWithIdentifier("HomePage") as! ViewController
self.presentViewController(loginPageView, animated: true, completion: nil)
}

just replace the below code in your pressed button action. because when you are skipping and going to home view controller. you are presenting the controller so navigation is no more in the stack. and again when you press on the computer button it will try to push the controller and because navigation is no more in the stack it is crashing. when you are pressing the skip button try to pop view controller. like below.
func pressed(sender: UIButton!) {
audioPlayer?.stop();
self.navigationController?.popToRootViewControllerAnimated(true)
// OR
self.navigationController?.popViewControllerAnimated(true)
}

Related

How to push a ViewController from a UIButton that is embedded in Tab Bar Controller

In want to have a button floating next to my Tab Bar. When pressed, this button will open a View that can be Navigated (so a View Controller embedded in a Navigation Controller(?)).
In UITabBarController {
ViewDidLoad() {
super.viewDidLoad()
//I have my 5 tab bar items set up programatically here.
//The middle tab bar item is disabled because the button is on top of it
setupMiddleButton()
}
My setupMiddleButton function
let menuButton = UIButton(frame: CGRect(x: 0, y: 0, width: 52, height: 52))
//..various styling and alignment values...
view.addSubview(menuButton)
menuButton.addTarget(self, action: #selector(menuButtonAction(sender:)), for: .touchUpInside)
finally I've tried to add the code to push the view controller, however I receive nil when tapping the button.
#objc private func menuButtonAction(sender: UIButton) {
let createController = CreateViewController()
let nav3 = UINavigationController(rootViewController: createController)
nav3.navigationController!.pushViewController(createController, animated: true)
I think that you may be passing the wrong parameter to the menuButtonAction function, try to change your code like this:
func setupMiddleButton() {
let menuButton = UIButton(frame: CGRect(x: 0, y: 0, width: 52, height: 52))
//..various styling and alignment values...
view.addSubview(menuButton)
menuButton.addTarget(self, action: #selector(menuButtonAction(_:)), for: .touchUpInside)
}
...
#objc private func menuButtonAction(_ sender: UIButton) {
...
}
So I figured it out. Turns out it was much simpler than I thought, which makes me think I was explaining myself poorly in the question. Anyway, here's the code that worked for me.
let myViewController = ViewController()
let nav = UINavigationController(rootViewController: myViewController)
self.present(nav, animated:true, completion: nil)

Custom Tab Bar To Navigate Between View Controller

I have a tab bar which i have set up using storyboard. In the tab bar, i have a custom button in the middle which looks like:
It was set up using:
class TabBarViewController: UITabBarController {
let button = UIButton.init(type: .custom)
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
button.setImage(UIImage(named: "assetIcon"), for: .normal)
button.backgroundColor = .blue
button.layer.cornerRadius = 35
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
self.view.insertSubview(button, aboveSubview: self.tabBar)
self.view.layoutIfNeeded()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let distance = ((self.view.bounds.height)/100)*11
// safe place to set the frame of button manually
button.frame = CGRect.init(x: self.tabBar.center.x - 32, y: self.view.bounds.height - distance, width: 70, height: 70)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#objc func buttonAction(){
// no actions here yet as I dont know what to put
}
}
As seen above, i created an action for the button to navigate to a specific view like how other tab bar button should act. However, I am not sure how to navigate or rather should i say, I dont know what i should be putting in the custom tab bar button
I'm guessing you want to display a view controller using the button.
Instantiate and display the View Controller using the following:
let storyboard = UIStoryboard(name: "StoryboardName", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "ViewControllerIdentifier")
self.present(controller, animated: true, completion: nil)
When the button is tapped, I believe you need to be using the selectedViewController property to specify which view to display. Here's the documentation on the Tab Bar Controller: https://developer.apple.com/documentation/uikit/uitabbarcontroller

Add UIBarButtomItem as Child of UITabBarController

I have a UIViewController with a UITableView embedded in a UINavigationController, that starts a UITabBarController. The navigation bar is displayed including the back button and I can change the title of the navigation item programmatically from the UITabBarController.
But I can't add a UIBarButtonItem to the child controllers of the UITabBarController. Neither in the storyboard, nor programmatically.
I also tried to embed the child controller in a UINavigationController, but that just added a second navigation bar. How do I add UIBarButtonItems from a child of a UITabBarController?
In your storyboard, your view controller is inside navigation controller. And your child view controller is INSIDE tab bar controller of your view controller. You're not able to add bar button because you're not able to access navigationController property (which is nil in your child controller case.)
Debug this by accessing navigationController and tabBarController. In your case it should be tabBarController?.navigationController most probably.
EDIT
This is how I maintain navigation bar in code:
final class MyVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
setupNavigationBar(withTitle: "MyVC")
}
}
extension UIViewController {
func setupNavigationBar(withTitle title: String? = nil) {
let backButton = UIBarButtonItem(image: #imageLiteral(resourceName: back), style: .plain, target: self, action: #selector(popVC(animated:)))
backButton.tintColor = .white
navigationItem.leftBarButtonItem = backButton
navigationItem.title = title
}
#objc
func popVC(animated: Bool = true) {
navigationController?.popViewController(animated: true)
}
}
Try the following code for set the left and right BarButton programatically.You can add the given code in viewDidload your child TabBarController.
let cancelBtn = UIButton(type: .custom)
cancelBtn.frame = CGRect(x: 0, y: 0, width: 40, height: 15)
cancelBtn.setTitle("Cancel", for: .normal)
cancelBtn.setTitleColor(UIColor.init(red: 240/255, green: 36/255, blue: 70/255, alpha: 1.0), for: .normal)
cancelBtn.addTarget(self, action: #selector(cancelTapped), for: .touchUpInside)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: cancelBtn)
let resetBtn = UIButton(type: .custom)
resetBtn.setTitle("Reset", for: .normal)
resetBtn.setTitleColor(UIColor.init(red: 240/255, green: 36/255, blue: 70/255, alpha: 1.0), for: .normal)
resetBtn.addTarget(self, action: #selector(resetTapped), for: .touchUpInside)
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: resetBtn)
and also add the following codes to make it sure the property of navigation bar is true..
override func viewWillAppear(_ animated: Bool)
{
super.viewWillAppear(animated)
// Hide the navigation bar on the this view controller
self.navigationController?.setNavigationBarHidden(true, animated: animated)
}
override func viewWillDisappear(_ animated: Bool)
{
super.viewWillDisappear(animated)
// Show the navigation bar on other view controllers
self.navigationController?.setNavigationBarHidden(false, animated: animated)
}
I have one suggestion for you. Please just remove the Show Segue Between the Person List ViewController to the Person Detail ViewController. and then you embed In Navigation to Person Detail ViewController.
And on the didselect tableview method set the 'Person Detail ViewController` as RootViewController Then You can add the NavigationBar Item in the childViewController also.

Custom navigation bar button and action to open a new viewController

I´m trying to make a new custom navigation bar button with my own image. That´s working fine, but I´m trying to open a new view controller when I press that button. Unfortunately that doesn´t work and I have no idea how I should do it.
let testUIBarButtonItem = UIBarButtonItem(image: UIImage(named: "Image.png"), style: .plain, target: self, action: nil)
self.navigationItem.rightBarButtonItem = testUIBarButtonItem
func clickButton(sender: UIBarButtonItem){}
That´s my code right now and its inside my viewDidLoad. My intention is to perform a show detail Segue comment.
Can someone help me ?
why don't you just use a UIButton and assign it as bar button item as suggested in this thread:
UIBarButtonItem: target-action not working?
let button = UIButton(type: .Custom)
if let image = UIImage(named:"icon-menu.png") {
button.setImage(image, forState: .Normal)
}
button.frame = CGRectMake(0.0, 0.0, 30.0, 30.0)
button.addTarget(self, action: #selector(MyClass.myMethod), forControlEvents: .TouchUpInside)
let barButton = UIBarButtonItem(customView: button)
navigationItem.leftBarButtonItem = barButton
If you are using a Storyboard, add a manual segue to your ViewController and give it an identifier. Then you have to call performSegue in your custom navigationbar button's IBAction.
func clickButton(sender: UIBarButtonItem){
self.performSegue(withIdentifier: "yourSegueIdentifier", sender: nil)
}

Swift 3 - Add BarButtonItem To NavigationBar On Each ViewController Without Repeating Code

I have a BarButtonItem I want to add to every single ViewController in my app. How can I do this without having to copy/paste the button creation code and the action function into each ViewController? I would prefer reusability instead of having the same code in every ViewController.
Button Code:
// Settings button
let btn = UIButton(type: .custom)
btn.setImage(UIImage(named: "icon-settings"), for: .normal)
btn.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
btn.addTarget(self, action: #selector(showSettings(sender:)), for: .touchUpInside)
let settingsBtn = UIBarButtonItem(customView: btn)
self.navigationItem.setRightBarButton(settingsBtn, animated: false)
The Action:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "SettingsVC") as! SettingsViewController
self.navigationController?.show(vc, sender: self)
I've tried adding this code to a separate Utility class, but you can't perform the segue from it since there is no way to access the button's parent ViewController from the action function if it is declared in the Utility class. I also tried subclassing UINavigationController and assigning that subclass to the NavigationController in my Storyboard, but it didn't work.
You can do this by adding a BaseViewController and inserting the code there. After that, on your rootviewController of your navigationController, you just extend from this BaseViewController. Doing that, and calling super in that function it will always having that code available and you don't need to repeat in every viewcontroller.
import UIKit
class BaseViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Settings button
let btn = UIButton(type: .custom)
btn.setImage(UIImage(named: "icon-settings"), for: .normal)
btn.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
btn.addTarget(self, action: #selector(showSettings(sender:)), for: .touchUpInside)
let settingsBtn = UIBarButtonItem(customView: btn)
self.navigationItem.setRightBarButton(settingsBtn, animated: false)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
And then in your view controller you just extend BaseViewController
class ViewController: BaseViewController {
override func viewDidLoad() {
super.viewDidLoad()
//Button should already appear here
}
Note that ViewController should be your root view controller.

Resources