xcode swift nulpad with next button not working - iphone

I am relatively new to coding so please bear with me. I have written a simple app which has 6 text fields that need to completed before an action button is pressed to perform a mathematical calculation.
I have everything done but i can't get my next button to move to the next text field. I have added the tool bar and the done and next button but when i press the next button the app crashes and i get a "Thread 1: signal SIGABRT".
I have been through the internet and I am struggling to see how do do it. I would have thought this would be pretty straight forward.
I just can't make the next button perform the action to the next box.
Here is my code
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
//IBOutlet UITextFields are here
override func viewDidLoad() {
super.viewDidLoad()
let toolBar = UIToolbar()
toolBar.barStyle = .default
toolBar.isTranslucent = true
toolBar.sizeToFit()
let flexibleSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let fixedSpaceButton = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
let doneButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.done, target: self, action: #selector(self.doneClicked))
let nextButton = UIBarButtonItem(title: "Next", style: .plain, target: self, action: #selector(self.textFieldShouldReturn(_:)))
toolBar.setItems([fixedSpaceButton, nextButton, flexibleSpace, doneButton], animated: false)
toolBar.isUserInteractionEnabled = true
box1.delegate = self
box2.delegate = self
box3.delegate = self
box4.delegate = self
box5.delegate = self
box6.delegate = self
box1.becomeFirstResponder()
}
func doneClicked() {
view.endEditing(true)
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool
{
switch textField
{
case box1: box2.becomeFirstResponder()
break
case box2: box3.becomeFirstResponder()
break
case box3: box4.becomeFirstResponder()
break
case box4: box5.becomeFirstResponder()
break
case box5: box6.becomeFirstResponder()
break
default: textField.resignFirstResponder()
}
return true
}
//IBAction for maths calculations are here
I appreciate any help in advance. I literally have no hair left.
Thanks

Related

I want to switch the screen when the Label named New Account is pressed, but the application keeps crashing. Can you help me?

lazy var newAccountLabel: UILabel = {
let newAccountLabel = UILabel()
newAccountLabel.text = " New Account"
newAccountLabel.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: LoginViewController.self, action: #selector(LoginViewController.newAccountLabelTapped(_:)))
newAccountLabel.addGestureRecognizer(tap)
newAccountLabel.textColor = .systemGray
return newAccountLabel
}()
The creation of the label I want to click on.
#objc func newAccountLabelTapped(_ sender: UIButton){
let goToVc = RegisterViewController()
self.present(goToVc, animated: true, completion: nil)
}
The action function that the transition should be.
Replace LoginViewController.self with self
let tap = UITapGestureRecognizer(target: self, action: #selector(LoginViewController.newAccountLabelTapped(_:)))

How to set textField becomeFirstResponder via selector

I wrote a UITextfield extension to build my own toolbar for custom inputs:
func addToolbar(selector: Selector? = nil) {
let action = selector == nil ? #selector(resignFirstResponder) : selector
let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: action)
let toolbar = UIToolbar()
toolbar.items = [flexibleSpace, doneButton]
toolbar.sizeToFit()
toolbar.layoutIfNeeded()
inputAccessoryView = toolbar
returnKeyType = .done
}
I use it like this:
let myPickerView = UIPickerView()
myPickerView.dataSource = myPickerViewBehavior
myPickerView.delegate = myPickerViewBehavior
if let selected = value {
let selectedIndex = PickableItemType.index(of: selected.rawValue)
myPickerView.selectRow(selectedIndex, inComponent: 0, animated: true)
}
myTextField.delegate = self
myTextField.inputView = myPickerView
myTextField.addToolbar(selector: #selector(nextTextField.becomeFirstResponder))
As you can imagine I want the next UITextField to becomeFirstResponder after the user pressed done in the toolbar.
But nothing happening.
For testing I've tried using a simple #objs func with print statement and/or nextTextField.becomeFirstResponder inside, same result.
I've also tried to use UITapGestureRecognizer with #selector(nextTextField.becomeFirstResponder), also same result.
So I guess it has something to do with the #selector mechanic why the code doesn't work.
P.S.: if selector == nil inside addToolbar , #selector(resignFirstResponder) works fine.
I believe the problem is caused by the wrong target: while setting up doneButton.
If you also supply the target in addToolbar: method like:
func addToolbar(target: Any? = nil, selector: Selector? = nil) {
let object = target ?? self
let action = selector ?? #selector(resignFirstResponder)
let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: object, action: action)
let toolbar = UIToolbar()
toolbar.items = [flexibleSpace, doneButton]
toolbar.sizeToFit()
toolbar.layoutIfNeeded()
inputAccessoryView = toolbar
returnKeyType = .done
}
This should work:
firstTextField.addToolbar(target: secondTextField, selector: #selector(becomeFirstResponder))
Here's a small test result:
https://imgur.com/R7R1ee9

UIDatePicker: select current date (swift)

I have a UIDatePicker in which some date is set by initial. With addTarget, I listen to thevalueChanged events and everything works correctly when the wheel is spinning.
I want to allow users to directly select the initial date (for example, by clicking on it). But now the event comes only when the wheel is spinning. To put the current date, the user will have to:
Put a new date
Go to the previous date
My code:
class Picker {
init() {
let datePicker = UIDatePicker()
datePicker.setDate(Date(), animated: false) // Set initial date
datePicker.addTarget(self, action: #selector(handleDatePicker(sender:)), for: .valueChanged)
}
#objc func handleDatePicker(sender: UIDatePicker) {
print(sender.date)
}
}
Picker()
Screenshot:
SOLUTION:
The most correct solution turned out to be the addition the UIToolBar with Done button. The code can be found here: example with UIToolBar
to select first index value on click done button in datePicker
func pickUp(_ textField : UITextField){
// UIPickerView
self.myPickerView = UIPickerView(frame:CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 216))
self.myPickerView.delegate = self
self.myPickerView.dataSource = self
self.myPickerView.backgroundColor = UIColor.white
textField.inputView = self.myPickerView
// ToolBar
let toolBar = UIToolbar()
toolBar.barStyle = .default
toolBar.isTranslucent = true
toolBar.tintColor = UIColor.darkGray
toolBar.sizeToFit()
// Adding Button ToolBar
let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(UrVC.doneClick))
let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(UrVC.cancelClick))
toolBar.setItems([cancelButton, spaceButton, doneButton], animated: false)
toolBar.isUserInteractionEnabled = true
textField.inputAccessoryView = toolBar
}
#objc func doneClick() {
pickerTxtfld.resignFirstResponder()
let indexPath = myPickerView.selectedRow(inComponent: 0)
pickerTxtfld.text = dataArray[indexPath]
}
#objc func cancelClick() {
pickerTxtfld.resignFirstResponder()
}

How to add action to a programmatically-made button?

Since I was having issues creating a button via storyboard, I went about initiating a right nav bar button through code - found via this question How can I go back to the initial view controller in Swift?. This code is meant to take me back to my root view controller.
So here is the code as it stands at the moment.
let button1 = UIBarButtonItem(image: UIImage(named: "HomeM25.png"), style: .plain, target: self, action: #selector(getter: UIDynamicBehavior.action))
self.navigationItem.rightBarButtonItem = button1
func button() {
self.view.window?.rootViewController?.dismiss(animated: true, completion: nil)
}
I was under the impression that if I were to change the
action: #selector(getter: action)
I would be able to create a function following this button initialization like so
func action() {
self.view.window?.rootViewController?.dismiss(animated: true, completion: nil)
}
However, I am greeted with the "Use of local variable 'action' before its declaration'". I do not understand why this interpretation would not perform/why I would have to establish the action variable when its only use is a function name? Any help would be appreciated.
Update 1: Current Code
override func viewDidLoad() {
super.viewDidLoad()
let button1 = UIBarButtonItem(image: UIImage(named: "HomeM25.png"), style: .plain, target: self, action: #selector(action))
self.navigationItem.rightBarButtonItem = button1
func action() {
self.view.window?.rootViewController?.dismiss(animated: true, completion: nil)
}
Update 1: Also had to use a different function action to go back to the original view controller.
self.navigationController!.popToRootViewController(animated: true)
It should be #selector(action). And you can define function within a function. Move action outside of the viewDidLoad function. Try this.
override func viewDidLoad() {
super.viewDidLoad()
let button1 = UIBarButtonItem(image: UIImage(named: "HomeM25.png"), style: .plain, target: self, action: #selector(action))
self.navigationItem.rightBarButtonItem = button1
}
func action() {
self.view.window?.rootViewController?.dismiss(animated: true, completion: nil)
}

UIBarButton not changing

#IBOutlet weak var playStopButton: UIBarButtonItem!
var playStopArray = [UIBarButtonSystemItem.Pause, UIBarButtonSystemItem.Play]
var index = 0
#IBOutlet weak var image: UIImageView!
#IBAction func playButton(sender: UIBarButtonItem) {
println("pressed")
playStopButton = UIBarButtonItem(barButtonSystemItem: playStopArray[index], target: self, action: "startMusic:")
println("here")
if index == 0 {
index = 1
}
else {
index = 0
}
}
func startMusic() {
println("test")
}
I expected the bar button to change to the pause symbol, but with no luck. It prints both "pressed" and "here" but "test" does not work. Why is the image not changing?
Your approach is wrong.
In the following line,
playStopButton = UIBarButtonItem(barButtonSystemItem: playStopArray[index], target: self, action: "startMusic:")
you are actually creating a new instance of UIBarButtonItem. This button is not actually added into the view. Instead of adding the UIBarButtonItem through Interface Builder. You can create it programmatically.
Read this question for more information.
toggle between UIBarButtonSystemItemPlay and UIBarButtonSystemItemPause
var playButton:UIBarButtonItem!
var pauseButton:UIBarButtonItem!
func setup()
{
playButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Play, target: self, action: "startMusic:")
pauseButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Pause, target: self, action: "stopMusic:")
}
func startMusic:(button : UIBarButtonItem)
{
self.navigationItem.rightBarButtonItem = pauseButton // Switch to pause.
//Other code.
}
func stopMusic:(button : UIBarButtonItem)
{
self.navigationItem.rightBarButtonItem = playButton// Switch to play.
//Other code.
}
Here is my approach in Swift
func configureBars() {
isPlaying = false
// UIToolbar
let pickBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Search,
target: self,
action: "pickSong")
let playBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Play,
target: self,
action: "playPause")
let pauseBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Pause,
target: self,
action: "playPause")
let leftFlexBBI = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace,
target: nil,
action: nil)
let rightFlexBBI = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace,
target: nil,
action: nil)
playItems = [pickBarButtonItem, leftFlexBBI, playBarButtonItem, rightFlexBBI]
pauseItems = [pickBarButtonItem, leftFlexBBI, pauseBarButtonItem, rightFlexBBI]
toolbar.items = playItems
}
visit http://www.raywenderlich.com/36475/how-to-make-a-music-visualizer-in-ios
or you can check out my Github https://github.com/Charles-Hsu/MusicVisualizer