I have managed to code four UIBarButton items that appear when I run my app. However, when I click on one of the buttons (to go to a new screen), the app crashes with a SIGBART error. I know from previous experiences that this may be caused by not having outlets connect. But because I have coded the buttons to appear in my file, I am unsure of how to connect the outlet and actions through code. Any guidance would be much appreciated!
import UIKit
class navigationToolBar: UINavigationController, UIToolbarDelegate {
#IBOutlet weak var searchBarButton1: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
print(UIApplication.shared.statusBarFrame.height)//44 for iPhone x, 20 for other iPhones
navigationController?.navigationBar.barTintColor = .blue
self.toolbar.barTintColor = UIColor.black
var searchicon = UIImage(named: "searchicon")!
var protocolsicon = UIImage(named: "protocolsicon")!
var homeicon = UIImage(named: "homeicon")!
var toolsicon = UIImage(named: "toolsicon")!
let search1 = self.storyboard?.instantiateViewController(withIdentifier: "searchn") as! UINavigationController
let protocols1 = self.storyboard?.instantiateViewController(withIdentifier: "protocolsn") as! UINavigationController
let home1 = self.storyboard?.instantiateViewController(withIdentifier: "homen") as! UINavigationController
// let tools1 = self.storyboard?.instantiateInitialViewController(withIdentifier: "initial") as! imageViewController
// let info1 = self.storyboard?.instantiateViewController(withIdentifier: "Information") as! imageViewController
let toolBar = UIToolbar()
var items = [UIBarButtonItem]()
var searchBarButton1 = UIBarButtonItem(image: searchicon, style: .plain, target: self, action: Selector(("opensearchbar1")))
items.append(
UIBarButtonItem(image: searchicon, style: .plain, target: self, action: Selector(("opensearchbar1")))
)
items.append(
UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
)
items.append(
UIBarButtonItem(image: protocolsicon, style: .plain, target: self, action: Selector(("opensearchbar")))
)
items.append(
UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
)
items.append(
UIBarButtonItem(image: homeicon, style: .plain, target: self, action: Selector(("onClickBarButton:")))
)
items.append(
UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
)
items.append(
UIBarButtonItem(image: toolsicon, style: .plain, target: self, action: Selector(("onClickBarButton:")))
)
items.append(
UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
)
items.append(
UIBarButtonItem(image: toolsicon, style: .plain, target: self, action: Selector(("onClickBarButton:")))
)
func opensearchbar(_ sender: UIBarButtonItem) {
switch sender.tag {
case 1:
print("1")
break;
case 2:
print("error")
break;
case 3:
self.navigationController?.pushViewController(protocols1, animated: true)
break;
case 4:
print("error")
break;
case 5:
self.navigationController?.pushViewController(home1, animated: true)
break;
case 6:
print("error")
break;
case 7:
self.navigationController?.pushViewController(home1, animated: true)
break;
case 8:
print("error")
break;
// case 9:
// self.navigationController?.pushViewController(info1, animated: true)
// break;
default:
print("ERROR!!")
}
}
toolBar.setItems(items, animated: true)
toolBar.tintColor = .blue
toolbar.barStyle = UIBarStyle.default
toolBar.isTranslucent = true
view.addSubview(toolBar)
toolBar.translatesAutoresizingMaskIntoConstraints = false
if #available(iOS 11.0, *) {
let guide = self.view.safeAreaLayoutGuide
toolBar.trailingAnchor.constraint(equalTo: guide.trailingAnchor).isActive = true
toolBar.leadingAnchor.constraint(equalTo: guide.leadingAnchor).isActive = true
toolBar.bottomAnchor.constraint(equalTo: guide.bottomAnchor).isActive = true
toolBar.heightAnchor.constraint(equalToConstant: 44).isActive = true
}
else {
NSLayoutConstraint(item: toolBar, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1.0, constant: 0).isActive = true
NSLayoutConstraint(item: toolBar, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1.0, constant: 0).isActive = true
NSLayoutConstraint(item: toolBar, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1.0, constant: 0).isActive = true
toolBar.heightAnchor.constraint(equalToConstant: 44).isActive = true
}
}
func opensearchbar1 (_ sender: UIBarButtonItem) {
let search1 = self.storyboard?.instantiateViewController(withIdentifier: "searchn") as! ViewController
self.navigationController?.pushViewController(search1, animated: true)
}
}
Related
My swift code below which is all code no storyboard. Tries to save a switch's state using user defaults. So when the user segues to twoViewController and then segues backs to ViewController. The users switch setting is not being saved. There are no errors presented and I don't know what is going on.
import UIKit
class ViewController: UIViewController {
var nxtBTn = UIButton()
var mySwitch = UISwitch()
let userDefaults = UserDefaults.standard
var firstTimeAppLaunch: Bool {
get {
// Will return false when the key is not set.
return userDefaults.bool(forKey: "firstTimeAppLaunch")
}
set {}
}
#objc func switchAction(_ sender: UISwitch) {
userDefaults.set(sender.isOn, forKey: "mySwitchValue")
}
#objc func press() {
let segue = twoViewController()
segue.modalPresentationStyle = .fullScreen // actually .fullScreen would be better
self.present(segue, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
[nxtBTn,mySwitch].forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
view.addSubview($0)
$0.backgroundColor = .green
}
if !firstTimeAppLaunch {
// This will only be trigger first time the application is launched.
userDefaults.set(true, forKey: "firstTimeAppLaunch")
userDefaults.set(true, forKey: "mySwitchValue")
}
NSLayoutConstraint.activate([
nxtBTn.leadingAnchor.constraint(equalTo: view.leadingAnchor),
nxtBTn.topAnchor.constraint(equalTo: view.topAnchor),
nxtBTn.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 7/7, constant: 0),
nxtBTn.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.4, constant: 0),
mySwitch.leadingAnchor.constraint(equalTo: view.leadingAnchor),
mySwitch.bottomAnchor.constraint(equalTo: view.bottomAnchor),
mySwitch.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 7/7, constant: 0),
mySwitch.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.4, constant: 0),
])
mySwitch.addTarget(self, action: #selector(switchAction(_:)), for: .touchDown)
nxtBTn.addTarget(self, action: #selector(press), for: .touchDown)
view.backgroundColor = .white
}
override func viewDidAppear(_ animated: Bool) {
mySwitch.isOn = userDefaults.bool(forKey: "mySwitchValue")
}
}
class twoViewController : UIViewController{
var backBtn = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
backBtn.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(backBtn)
backBtn.backgroundColor = .systemGreen
NSLayoutConstraint.activate([
backBtn.leadingAnchor.constraint(equalTo: view.leadingAnchor),
backBtn.topAnchor.constraint(equalTo: view.topAnchor),
backBtn.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 7/7, constant: 0),
backBtn.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.4, constant: 0),
])
backBtn.addTarget(self, action: #selector(oneVC), for: .touchDown)
}
#objc func oneVC(){
let segue = ViewController()
segue.modalPresentationStyle = .fullScreen // actually .fullScreen would be better
self.present(segue, animated: true)
}
}
Everywhere you are saying for: .touchDown it is wrong. Change all of them to for: .primaryActionTriggered and things will improve.
enter image description hereI am making a user login page for my IOS App. I am trying to make everything programmatically without using a segue in the main story board. I have managed to go to the next page as you can see in the code and create a custom left back bar item. But I don't know how to go back to the first page when I click on that button. I have attached the screen shot of my story board and app below. Can you please tell me how I can go back to the first page by clicking the X button?
Here is my code:
import UIKit
class FirstPage: UIViewController {
let hgt = UIScreen.main.bounds.height/2
private let loginSignup: UIButton = {
let button = UIButton(type: .system)
button.setTitle("Login or Sign Up", for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)
button.setTitleColor(.green, for: .normal)
button.addTarget(self, action: #selector(loginSignupBtn), for: .touchUpInside)
return button
}()
#objc private func loginSignupBtn() {
let vc = self.storyboard!.instantiateViewController(withIdentifier: "Login") as! Login
vc.loadViewIfNeeded()
self.navigationController?.pushViewController(vc, animated: true)
self.navigationController?.isNavigationBarHidden = false
let backItem = UIBarButtonItem(title: "X ", style: UIBarButtonItem.Style.done, target: nil, action: nil)
let font = UIFont.boldSystemFont(ofSize: 26)
backItem.setTitleTextAttributes([NSAttributedString.Key.font:font] ,for: .normal)
backItem.tintColor = UIColor.green
vc.navigationItem.leftBarButtonItem = backItem
}
override func viewDidLoad() {
super.viewDidLoad()
setupLayout()
}
override func viewWillAppear(_ animated: Bool) {
}
private func setupLayout() {
let topImageContainerView = UIView()
//topImageContainerView.backgroundColor = .yellow
view.addSubview(topImageContainerView)
//enable auto layout
topImageContainerView.translatesAutoresizingMaskIntoConstraints = false
topImageContainerView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
topImageContainerView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
topImageContainerView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
topImageContainerView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.5).isActive = true
view.addSubview(loginSignup)
loginSignup.translatesAutoresizingMaskIntoConstraints = false
loginSignup.topAnchor.constraint(equalTo: view.topAnchor,constant:hgt/2).isActive = true
loginSignup.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
loginSignup.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
loginSignup.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.5).isActive = true
}
}
enter image description here
Here you need to add target and selector for when the x button is clicked
let backItem = UIBarButtonItem(title: "X ",
style: UIBarButtonItem.Style.done,
target: self, action:#selector(goBack))
#objc func goBack(_ bar:UIBarButtonItem) {
self.navigationController?.popToRootViewController(animated:true)
}
on textbox click pickerview should raise.in picker view i had added tool like this
picker.delegate = self
picker.dataSource = self
picker.showsSelectionIndicator = true
let toolBar = UIToolbar()
toolBar.barStyle = UIBarStyle.default
toolBar.isTranslucent = true
toolBar.tintColor = UIColor.black
//UIColor(red: 76/255, green: 217/255, blue: 100/255, alpha: 1)
toolBar.sizeToFit()
let addbutton = UIBarButtonItem(title: "+Add", style: UIBarButtonItemStyle.plain, target: self, action: #selector(GBEDasboardViewController.addproducts))
let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.plain, target: self, action: #selector(GBEDasboardViewController.addproducts))
toolBar.setItems([cancelButton, spaceButton, doneButton], animated: false)
toolBar.isUserInteractionEnabled = true
productname.inputView = picker
productname.inputAccessoryView = toolBar
on click addbutton pickerview should close and keypad should raise
func addproducts(){
self.view.endEditing(true)
}
pickerview is closing properly but how to raise the keypad.
you should replace your code with following.
let addbutton = UIBarButtonItem(title: "+Add", style: UIBarButtonItemStyle.plain, target: self, action: #selector(GBEDasboardViewController.addProducts))
let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.plain, target: self, action: #selector(GBEDasboardViewController.endEditing))
func addProducts(){
self.view.endEditing(true)
productname.inputView = nil
productname.becomeFirstResponder()
}
func endEditing() {
self.view.endEditing(true)
}
I got a custom UIPickerView from github (https://github.com/bendodson/MonthYearPickerView-Swift") and now I'm trying to connect it to a textfield with no luck. I managed to do it with the standard UiDatePicker using .addTarget and .valueChanged methods, but with this custom one addTarget throws an error. Now I only manage to get the textfield's inputView to the custom PickerView, but not save the input using my "Done" button that I created. What is it that I'm missing?
lazy var ExpireDatetextfeild: UITextField = {
let tf = LeftPaddedTextFeild()
tf.placeholder = "MM/YY"
tf.translatesAutoresizingMaskIntoConstraints = false
tf.addTarget(self, action: #selector(textfeildediting), for: .editingDidBegin)
return tf
}()
let DatePickerView: MonthYearPickerView = MonthYearPickerView()
func textfeildediting() {
let DatePickerView: MonthYearPickerView = MonthYearPickerView()
DatePickerView.backgroundColor = .white
let toolBar = UIToolbar()
toolBar.barStyle = UIBarStyle.default
toolBar.isTranslucent = true
toolBar.backgroundColor = UIColor.white
toolBar.sizeToFit()
let donebutton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.plain, target: self, action: #selector(DoneFunc))
let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.plain, target: self, action: #selector(cancelFunc))
toolBar.setItems([cancelButton, spaceButton, donebutton], animated: false)
toolBar.isUserInteractionEnabled = true
ExpireDatetextfeild.inputAccessoryView = toolBar
ExpireDatetextfeild.inputView = DatePickerView
}
func cancelFunc(sender: UIBarButtonItem) {
DatePickerView.isHidden = true
print("DatePickerPrint")
}
func DoneFunc(sender: UIBarButtonItem) {
DatePickerView.onDateSelected = { (month: Int, year:Int) in
let Yearstring = String(format: "%02d/%d", month, year)
print(Yearstring)
}
}
I've got a problem by dismissing a ViewController programmatically.
I connected both Controllers and if I press the Button, the Controller will be presented.
Here is my prepareForSegue method:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let VC = VC()
let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.Dark)
let blurredView = UIVisualEffectView(effect: blurEffect)
blurredView.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height + 64)
VC.view.frame = self.view.bounds
VC.view.backgroundColor = UIColor.clearColor()
VC.view.addSubview(blurredView)
VC.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext
var masterViewOfVC = (segue.destinationViewController as! SubjectSelectionViewController).masterView
blurredView.addSubview(masterViewOfVC)
masterViewOfVC.setTranslatesAutoresizingMaskIntoConstraints(false)
let views = ["masterView": masterViewOfVC]
let horizontalConstraintsForMasterView = NSLayoutConstraint.constraintsWithVisualFormat("H:|[masterView]|", options: .AlignAllCenterY, metrics: nil, views: views)
blurredView.addConstraints(horizontalConstraintsForMasterView)
let verticalConstraintsForMasterView = NSLayoutConstraint.constraintsWithVisualFormat("V:|[masterView]|", options: .AlignAllCenterX, metrics: nil, views: views)
blurredView.addConstraints(verticalConstraintsForMasterView)
(segue.destinationViewController as! VC).viewDidLoad()
self.presentViewController(VC, animated: true, completion: nil)
}
So and if I try to dismiss it it doesn't do anything. I already checked if the buttons works and it does.
Here is my code from the other controller:
//viewDidLoad
cancelButton.setTitle("Abbrechen", forState: UIControlState.Normal)
cancelButton.tintColor = UIColor.whiteColor()
cancelButton.addTarget(self, action: Selector("buttonAction:"), forControlEvents: UIControlEvents.TouchUpInside)
cancelButton.enabled = true
//my function
func buttonAction(sender:UIButton!) {
VC().dismissViewControllerAnimated(true, completion: nil)
}
UPDATE
I delete the segue in my Storyboard and I created a modal segue in the IBAction of my Button. I also initialise my "dismiss button" in this action.
Here is my code from the parentViewController:
#IBAction func SubjectSelctionButtonPressed(sender: UIBarButtonItem) {
let subjectSelectionViewController = SubjectSelectionViewController()
let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.Dark)
let blurredView = UIVisualEffectView(effect: blurEffect)
blurredView.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height + 64)
subjectSelectionViewController.view.frame = self.view.bounds
subjectSelectionViewController.view.backgroundColor = UIColor.clearColor()
subjectSelectionViewController.view.addSubview(blurredView)
subjectSelectionViewController.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext
var masterViewOfSubjectSelection = SubjectSelectionViewController().masterView
var buttonOfSubjectSelection = SubjectSelectionViewController().cancelButton
buttonOfSubjectSelection.setTitle("Abbrechen", forState: UIControlState.Normal)
buttonOfSubjectSelection.tintColor = UIColor.whiteColor()
buttonOfSubjectSelection.addTarget(self, action: Selector("buttonAction:"), forControlEvents: UIControlEvents.TouchUpInside)
blurredView.addSubview(masterViewOfSubjectSelection)
masterViewOfSubjectSelection.addSubview(buttonOfSubjectSelection)
masterViewOfSubjectSelection.setTranslatesAutoresizingMaskIntoConstraints(false)
let views = ["masterView": masterViewOfSubjectSelection]
let horizontalConstraintsForMasterView = NSLayoutConstraint.constraintsWithVisualFormat("H:|[masterView]|", options: .AlignAllCenterY, metrics: nil, views: views)
blurredView.addConstraints(horizontalConstraintsForMasterView)
let verticalConstraintsForMasterView = NSLayoutConstraint.constraintsWithVisualFormat("V:|[masterView]|", options: .AlignAllCenterX, metrics: nil, views: views)
blurredView.addConstraints(verticalConstraintsForMasterView)
self.presentViewController(subjectSelectionViewController, animated: true, completion: nil)
}
and the action from the button looks like this:
func buttonAction(sender:UIButton!) {
dismissViewControllerAnimated(true, completion: nil)
}
ok now, when the controller is presenting there is nothing except my elements which I created in the action. My viewDidLoad() method of my presenting Controller is called but the constraints and the formattings doesn't get called...
Here is my viewDidLoad() of my modalViewController:
titleLabel.setTranslatesAutoresizingMaskIntoConstraints(false)
cancelButton.setTranslatesAutoresizingMaskIntoConstraints(false)
separatorLine.setTranslatesAutoresizingMaskIntoConstraints(false)
subjectsTableView.setTranslatesAutoresizingMaskIntoConstraints(false)
subjectsTableView.delegate = self
titleLabel.text = "Unterrichtsfächer"
titleLabel.textColor = UIColor.whiteColor()
titleLabel.font = UIFont(name: "HelveticaNeue-Medium", size: 17)
separatorLine.backgroundColor = UIColor.whiteColor()
subjectsTableView.backgroundColor = UIColor.clearColor()
masterView.addSubview(titleLabel)
masterView.addSubview(cancelButton)
masterView.addSubview(separatorLine)
masterView.addSubview(subjectsTableView)
let views = ["line": separatorLine, "title": titleLabel, "button": cancelButton, "table": subjectsTableView]
let verticalConstraintsForElements = NSLayoutConstraint.constraintsWithVisualFormat("V:|-64-[line(2)][table]|", options: .AlignAllCenterX, metrics: nil, views: views)
masterView.addConstraints(verticalConstraintsForElements)
let horizontalConstraintsForSeparatorLine = NSLayoutConstraint.constraintsWithVisualFormat("H:|[line]|", options: .AlignAllCenterY, metrics: nil, views: views)
masterView.addConstraints(horizontalConstraintsForSeparatorLine)
let horizontalConstraintsForTableView = NSLayoutConstraint.constraintsWithVisualFormat("H:|[table]|", options: .AlignAllCenterY, metrics: nil, views: views)
masterView.addConstraints(horizontalConstraintsForTableView)
let verticalConstraintsForTitleLabel = NSLayoutConstraint.constraintsWithVisualFormat("V:[title(21)]-11-[line]", options: .AlignAllCenterX, metrics: nil, views: views)
masterView.addConstraints(verticalConstraintsForTitleLabel)
let horizontalAlignmentForTitleLabel = NSLayoutConstraint(item: titleLabel, attribute: NSLayoutAttribute.CenterX, relatedBy: .Equal, toItem: masterView, attribute: .CenterX, multiplier: 1, constant: -18)
masterView.addConstraint(horizontalAlignmentForTitleLabel)
let widthForTitleLabel = NSLayoutConstraint(item: titleLabel, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 137)
masterView.addConstraint(widthForTitleLabel)
let verticalConstraintsForCancelButton = NSLayoutConstraint.constraintsWithVisualFormat("V:[button(30)]-6-[line]", options: .AlignAllCenterX, metrics: nil, views: views)
masterView.addConstraints(verticalConstraintsForCancelButton)
let horizontalConstraintsForCancelButton = NSLayoutConstraint.constraintsWithVisualFormat("H:[button(90)]-7-|", options: .AlignAllCenterY, metrics: nil, views: views)
masterView.addConstraints(horizontalConstraintsForCancelButton)
Can anybody help me?
Thank you very much!!!
Your problem is that you are not pushing the other view to dismiss it, you are just adding the new view controller on top of the other view
You need to substitute this line
blurredView.addSubview(masterViewOfVC)
For
presentViewController(masterViewOfVC, animated: true, completion: nil)
Now when you call dismiss view controller all should just work
I haven't really checked all your code but to fix it quickly, you can make the instance of VC a class property.
So it'll look something like this:
class MainViewController: UIViewController {
var VC = UIViewController() // I would use an optional here but I've been down voted for suggesting people to use optionals.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
VC = VC()
// Your code
}
func buttonAction(sender:UIButton!) {
VC.dismissViewControllerAnimated(true, completion: nil)
}
}
Here I'm assuming you're using some kind of master - detail view so buttonAction is still accessible when you segue to VC.
If buttonAction is a method in VC itself, then just call dissmissViewControllerAnimated() on self with:
func buttonAction(sender:UIButton!) {
dismissViewControllerAnimated(true, completion: nil)
}
Either way, you'll have to call dissmissViewControllerAnimated() on the instance of VC. With VC() you'll just create a new instance which has "nothing" to do with the one that already exists.
Update:
If you've created SubjectSelectionViewController() in your storyboard, then you probably would want to instantiate it with:
let storyboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
let subjectSelectionViewController = storyboard.instantiateViewControllerWithIdentifier("YourIdentifier") as! SubjectSelectionViewController