How implement "Next" and "Done" functions of UITextField on Swift4? - ios

I have a formulary of login, with 3 fields and a button to login. I wants set a button in the keyboard do jump of UITextField to next when user ends write the content. Besides that, when user put text on last field, the button login is hidden behind keyboard! I tried choose the options on the attributes inspector, but I don't know how use this.
class ViewControllerAuthentication: UIViewController {
#IBOutlet weak var btEntrar: UIButton!
#IBOutlet weak var textPassword: UITextField!
#IBOutlet weak var textEmail: UITextField!
#IBOutlet weak var textURL: UITextField!
let alert = Alerta()
var url : String?
var email : String?
var password : String?
override func viewDidLoad() {
self.btEntrar.addTarget(self, action: #selector(clickEntrar), for: .touchUpInside)
}
#objc func clickEntrar(_ sender : UIButton) {
// Do anything
}
}

You can do it, using UITextFieldDelegate, like...
class ViewControllerAuthentication: UIViewController, UITextFieldDelegate {
#IBOutlet weak var textPassword: UITextField!
#IBOutlet weak var textEmail: UITextField!
#IBOutlet weak var textURL: UITextField!
override func viewDidLoad() {
textPassword.delegate = self
textEmail.delegate = self
textURL.delegate = self
textURL.returnKeyType = .next
textEmail.returnKeyType = .next
textPassword.returnKeyType = .default // or .done
}
public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
switch textField {
case textURL:
textEmail.becomeFirstResponder()
case textEmail:
textPassword.becomeFirstResponder()
case textPassword:
textField.resignFirstResponder()
default:
textField.resignFirstResponder()
}
return true
}
}
I suggest IQKeyboardManager, if you don't want to handle each field manually.

Related

How do I get my new text entry into a UITextfield to store when closing app?

I'm completely new to programming. Trying to learn Swift. I've created the UI for my app. A simple data entry app for weight lifting PB's. However when I close the app my data doesn't update to new stored values. How do assign a variable string to each UITextfield entry, which when I close the app it will display its last stored value?
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var benchPressPB: UITextField!
#IBOutlet weak var squatPB: UITextField!
#IBOutlet weak var deadliftPB: UITextField!
#IBOutlet weak var ohpPB: UITextField!
#IBOutlet weak var rackPullPB: UITextField!
#IBOutlet weak var legPressPB: UITextField!
#IBOutlet weak var pullUpsPB: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
self.benchPressPB.delegate = self
self.squatPB.delegate = self
self.deadliftPB.delegate = self
self.ohpPB.delegate = self
self.rackPullPB.delegate = self
self.legPressPB.delegate = self
self.pullUpsPB.delegate = self
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}
P.S this may completely wrong and long already, but currently its achieving what I want it do, just not saving new inputted data. If there's any shorter way to get the keyboard to hide on return, let me know!
Your current code doesn't do anything with the values a user enters into your text fields.
You should
Set up a model object to hold the values that the user enters.
In your textFieldShouldReturn, collect the user input and save it
into your model.
Decide on how you want to persist your app's state so it restores
when the app is launched. At it's simplest, this could be saving each
string to a different key/value pair in UserDefaults, or grouped
together in a dictionary or an array.
The code might look something like this: (not tested. Not even compiled. It will need cleanup before you can use it:
#IBOutlet weak var benchPressPB: UITextField!
#IBOutlet weak var squatPB: UITextField!
#IBOutlet weak var deadliftPB: UITextField!
#IBOutlet weak var ohpPB: UITextField!
#IBOutlet weak var rackPullPB: UITextField!
#IBOutlet weak var legPressPB: UITextField!
#IBOutlet weak var pullUpsPB: UITextField!
var textFields = [UITextField]
var textFieldKeys = [
"benchPressPB",
"squatPB",
"deadliftPB",
"ohpPB",
"rackPullPB",
"legPressPB",
"pullUpsPB"
]
var textFieldStrings = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// Note that you can hook up the delegates for your
// text fields in your Storyboard.
self.benchPressPB.delegate = self
self.squatPB.delegate = self
self.deadliftPB.delegate = self
self.ohpPB.delegate = self
self.rackPullPB.delegate = self
self.legPressPB.delegate = self
self.pullUpsPB.delegate = self
textFields = [benchPressPB, squatPB, deadliftPB, ohpPB, rackPullPB, legPressPB, pullUpsPB]
// Read values from UserDefaults into the text fields.
for (index, key) in textFieldKeys.enumerated() {
let aValue = UserDefaults.standard.string(forKey: key)
textFields[index].text = aValue
textFieldStrings.append(aValue ?? "")
}
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
let newText = textField.text
if let index = textFields.firstIndex(of: textField) {
textFieldStrings[index] = newText
UserDefaults.standard.set(newText, forKey: textFieldKeys[index])
}
return true
}
You can subclass UITextField and add a target for editing changed. Every time your text changes you can simply save its new value into user defaults. To make sure you use a unique key for each field you can override the accessibilityIdentifier and implement didSet to load the old values when you set its identifier:
import UIKit
class PersistentTextField: UITextField, UITextFieldDelegate {
override var accessibilityIdentifier: String? {
didSet {
text = UserDefaults.standard.string(forKey: accessibilityIdentifier ?? "")
}
}
override func didMoveToSuperview() {
addTarget(self, action: #selector(editingChanged), for: .editingChanged)
autocapitalizationType = .none
autocorrectionType = .no
delegate = self
}
#objc func editingChanged(_ textField: UITextField) {
UserDefaults.standard.set(text ?? "", forKey: accessibilityIdentifier ?? "")
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
resignFirstResponder()
return true
}
}
Then in your view controller just make sure to set their id when your view loads:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var benchPressPB: PersistentTextField!
#IBOutlet weak var squatPB: PersistentTextField!
#IBOutlet weak var deadliftPB: PersistentTextField!
#IBOutlet weak var ohpPB: PersistentTextField!
#IBOutlet weak var rackPullPB: PersistentTextField!
#IBOutlet weak var legPressPB: PersistentTextField!
#IBOutlet weak var pullUpsPB: PersistentTextField!
override func viewDidLoad() {
super.viewDidLoad()
benchPressPB.accessibilityIdentifier = "bench press"
squatPB.accessibilityIdentifier = "squat"
deadliftPB.accessibilityIdentifier = "dead lift"
ohpPB.accessibilityIdentifier = "ohp"
rackPullPB.accessibilityIdentifier = "rack pull"
legPressPB.accessibilityIdentifier = "leg press"
pullUpsPB.accessibilityIdentifier = "pull ups"
}
}

Not woking UIView ishidden after change UILabel text value in swift

I want to change uilabel value and show uiview that has hide like a popup windows.
When I touch a button, that code print "setPopupView 0".
but doesn't show settingView.
and I touch a button again.
print "setPopupView 0" and show settingView.
so When "settingLabelValueUnit text" has changed not show settingView,
but when "settingLabelValueUnit text" has not changed show settingView.
(It means "settingLabelValue text" is same as input value)
I don't know why.
Anyone can help me?
Thank you
here is my swift code.
class ViewController: UIViewController {
#IBOutlet weak var workoutScrollView: UIScrollView!
#IBOutlet weak var settingView: UIView!
#IBOutlet weak var settingLabelValueUnit: UILabel!
#IBOutlet weak var imgSettingBGcal: UIImageView!
#IBOutlet weak var imgSettingBGdis: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
self.imgSettingBGcal.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(calSettingClick)))
self.imgSettingBGdis.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(disSettingClick)))
}
func calSettingClick(sender: UITapGestureRecognizer) {
setPopupView(0)
}
func disSettingClick(sender: UITapGestureRecognizer) {
setPopupView(1)
}
func showPopup (_ settype:Int) {
switch settype {
case 0:
print("setPopupView 0")
self.settingLabelValueUnit.text = "Set1"
self.workoutScrollView.isHidden = true
self.settingView.isHidden = false
case 1:
print("setPopupView 0")
self.settingLabelValueUnit.text = "Set2"
self.workoutScrollView.isHidden = true
self.settingView.isHidden = false
}
}
}

UIScrollView is being reset when editing UITextField

I'm new in Swift 3, and I just notice that we need to scroll a view since the keyboard can go over the some widgets as we type in text fields, like in this video. Fixing UITextField-Keyboard Problems (Swift in Xcode).
However, I am having an unfortunate behaviour even before programmatically scrolling the view. My view keeps being reset to its initial position. I made a video showing this behaviour.
I can't find mentions for this problem. Would someone have a clue?
[EDITED]
Here is the widgets are structured
Here is my View Controller code:
import UIKit
import AVFoundation
class SignUpController: UIViewController, UITextFieldDelegate
{
#IBOutlet var scrollView: UIScrollView!
#IBOutlet var stackView: UIStackView!
#IBOutlet var usernameTextField: UITextField!
#IBOutlet var passwordTextField: UITextField!
#IBOutlet var confirmationTextField: UITextField!
#IBOutlet var emailTextField: UITextField!
#IBOutlet var phoneTextField: UITextField!
#IBOutlet var firstNameTextField: UITextField!
#IBOutlet var lastNameTextField: UITextField!
#IBOutlet var signUpButton: UIButton!
var keyboardHeigh:CGFloat!
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.scrollView.contentSize = self.stackView.frame.size
self.scrollView.contentSize.height += self.stackView.frame.minY + 20
}
override func viewDidLoad() {
super.viewDidLoad()
let textFields :[UITextField] =
[
usernameTextField,
passwordTextField,
confirmationTextField,
emailTextField,
phoneTextField,
firstNameTextField,
lastNameTextField,
]
for i in 0..<textFields.count
{
textFields[i].delegate = self
textFields[i].tag = i
}
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillShow),
name: .UIKeyboardWillShow, object: nil)
}
func keyboardWillShow(notification: NSNotification)
{
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue
{
keyboardHeigh = keyboardSize.height
}
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool
{
// Try to find next responder
if let nextField = textField.superview?.viewWithTag(textField.tag + 1) as? UITextField
{
nextField.becomeFirstResponder()
}
else
{
// Not found, so remove keyboard.
textField.resignFirstResponder()
}
return false
}
}
1.You can take UItableViewController with static cell,
2.Put textField inside cell.
3.Make selection for cell none.
4.Make separator none.
It will work fine.

How do i get the Id of text view with radio Buttons clicked

For the radioButtons I have used Class in the button and for the indicator to buttons i have used the labels.
These are My TextView
#IBOutlet weak var TextViewEveryNewMessage: UILabel!
#IBOutlet weak var TextViewWeekly: UILabel!
#IBOutlet weak var TextViewDaily: UILabel!
#IBOutlet weak var TextViewMonthly: UILabel!
These are my Radio Buttons
#IBOutlet weak var RadioBtnMonthly: SSRadioButton!
#IBOutlet weak var RadioBtnWeekly: SSRadioButton!
#IBOutlet weak var RadioBtnDefaultChecked: SSRadioButton!
#IBOutlet weak var RadioBtnDaily: SSRadioButton!
As soon as i press the ok button i need to save the checkedRadio Button text somewhere and i have done it like this.
#IBAction func OkButton(sender: UIButton) {
SwiftSpinner.show(kLoadingText)
if RadioBtnDefaultChecked.selected{
preferencesConditions.notificationFrequency = self.TextViewEveryNewMessage.text
}else if RadioBtnDaily.selected{
preferencesConditions.notificationFrequency = self.TextViewDaily.text
}else if RadioBtnWeekly.selected{
preferencesConditions.notificationFrequency =
self.TextViewWeekly.text
}else{
preferencesConditions.notificationFrequency = self.TextViewMonthly.text
}
Is this correct way i am doing.Or there are any other approach. Please suggest me.
Instead of assigning a value for preferencesConditions.notificationFrequency in OkButton(sender: UIButton), you should do it in each of the SSRadioButton buttons and that's by calling SSRadioButtonControllerDelegate - didSelectButton:
func didSelectButton(aButton: UIButton?) {
print(aButton)
if aButton === RadioBtnDefaultChecked {
preferencesConditions.notificationFrequency = self.TextViewEveryNewMessage.text
}else if aButton === RadioBtnDaily {
preferencesConditions.notificationFrequency = self.TextViewDaily.text
}else if aButton === RadioBtnWeekly {
preferencesConditions.notificationFrequency =
self.TextViewWeekly.text
}else{
preferencesConditions.notificationFrequency = self.TextViewMonthly.text
}
}
Don't forget to conform the delegate to the viewController:
var radioButtonController: SSRadioButtonsController?
override func viewDidLoad() {
radioButtonController = SSRadioButtonsController(buttons: RadioBtnDefaultChecked, RadioBtnDaily, RadioBtnWeekly)
radioButtonController!.delegate = self
radioButtonController!.shouldLetDeSelect = true
}
The IBAction should be like:
#IBAction func OkButton(sender: UIButton) {
SwiftSpinner.show(kLoadingText)
}
For more information, check SSRadioButtonsController.
Hope this helped.

Disable multiple buttons easy way?

Is there any easy way I can do this? Let's say I have 10 different buttons and a textbox.
#IBOutlet var button1: UIButton!
#IBOutlet var button2: UIButton!
#IBOutlet var button3: UIButton!
#IBOutlet var button4: UIButton!
#IBOutlet var button5: UIButton!
#IBOutlet var button6: UIButton!
#IBOutlet var button7: UIButton!
#IBOutlet var button8: UIButton!
#IBOutlet var button9: UIButton!
#IBOutlet var button10: UIButton!
If textBox.text is "bt1", i want only enable button1, and disable the rest, and if textbox.text is "bt2", i want to only enable button2, and disable the rest, and so on...
You can create an IBOutletCollection of UIButton.
And accessing them like that:
button[0].enabled = false
Iterate through the array to disable all button.
UPDATED:
As I understand it you want to enable/disable buttons depending on some text entered into a textField. I'm assuming you have a method which is called from one of the textField delegate methods.
I'm also assuming that there is a 1 to 1 mapping from the text you enter to the buttons i.e that the user has to type exactly "btn1" - they can't do "button1" or "button 1" or any other variation. This is quite an odd requirement - are you sure this is what you really want?
First, as before put the buttons in an 'IBOutlet' collection:
#IBOutlet var allButtons : [UIButton]!
Then, use an enumeration to map the textbox text to the index of the buttons in the collection
enum ButtonMapping : String {
case button1 = "btn1"
case button2 = "btn2"
//and so on
func buttonIndex() -> Int {
switch(self) {
case button1: return 0
case button2: return 1
//and so on
}
}
}
Then just do something like:
func disableButtonsForText(text:String) {
if let mapping = ButtonMapping(rawValue:text) {
let activeButton = allButtons[mapping.buttonIndex]
for button in allButtons {
if button != activeButton {
button.enabled = false
}
}
}
}
This will change the state of the buttons only when the let binding is successful - i.e. when the string supplied to the ButtonMapping constructor is a valid button name. In all other cases, the state of the buttons won't change. You might want to consider adding an else clause to reset the state of the buttons to normal if the text is not recognised - not sure what you want here.
Note that you mustn't necessarily create an array of your buttons. As an alternative---given that these are all the buttons in your View Controller---you can make use of Mirror(reflecting: ...:
/* ViewController.swift */
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var button1: UIButton!
#IBOutlet weak var button2: UIButton!
#IBOutlet weak var button3: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
button1.enabled = true
button2.enabled = true
button3.enabled = true
setEnableValueForAllButtons(false, exceptForButton: "button2")
print(button1.enabled)
print(button2.enabled)
print(button3.enabled)
/* button1.enabled = false
button2.enabled = true
button3.enabled = false */
}
func setEnableValueForAllButtons(toValue: Bool, exceptForButton: String) {
let buttons = Mirror(reflecting: self).children.filter { $0.value is UIButton && ($0.label ?? "") != exceptForButton}
for button in buttons {
(button.value as? UIButton)?.enabled = toValue
}
}
}
If you want to only show the button whose property name is entered into a text field, you can simply extend the example above to include the text field, and call the setEnableValueForAllButtons(...) function from the UITextFieldDelegate method textFieldShouldReturn (hence after you press return after entering a string in the text field) as follows:
/* ViewController.swift */
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var button1: UIButton!
#IBOutlet weak var button2: UIButton!
#IBOutlet weak var button3: UIButton!
#IBOutlet weak var textBox: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
button1.enabled = false
button2.enabled = false
button3.enabled = false
textBox.delegate = self
}
func setEnableValueForAllButtons(toValue toValue: Bool, exceptForButton: String) {
let buttons = Mirror(reflecting: self).children.filter { $0.value is UIButton && ($0.label ?? "") != exceptForButton}
for button in buttons {
(button.value as? UIButton)?.enabled = toValue
}
}
// UITextFieldDelegate
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
setEnableValueForAllButtons(toValue: true, exceptForButton: "")
setEnableValueForAllButtons(toValue: false, exceptForButton: textField.text ?? "")
return true
}
}
If it's important for you to use triggers "bt1", "bt2" and so on, you could just rename the names of the button outlets to these values.

Resources