I'm trying to convert a UITextField object to a String so that I can pass it to a function in my model file. But it is printing a blank even after I type in some characters in the name input text field and then click outside of it. Why is nothing stored there?
In view controller file:
#IBOutlet weak var nameInputText: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
nameInputText.delegate = self
let text: String = nameInputText.text!
print(text) //this prints a blank
model.validateName(nametext: text)
}
It should be like below
#IBOutlet weak var usernameInputText : UITextField!
override func viewDidLoad() {
super.viewDidLoad()
usernameInputText.delegate = self
}
func ClickOnButton()
{
let text: String = usernameInputText.text!
print(text) //this prints My text
model.validateName(nametext: text)
}
func textField(_ textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String)
-> Bool
{
let text: String = usernameInputText.text!
print(text) //this prints My text
model.validateName(nametext: text)
}
viewDidLoad gets called before your ViewController would be visible to the user, so any text field can only contain text if you have set that text before (in InterfaceBuilder or code). If you want to access user input from that text field, you should either do that in textFieldDidEndEditing or in any other function which you know can only be called after the user interaction happened.
#IBOutlet weak var nameInputText: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
nameInputText.delegate = self
}
extension ViewController: UITextFieldDelegate {
func textFieldDidEndEditing(_ textField: UITextField) {
model.validateName(nametext: textField.text)
}
}
Related
I am adding to my Xcode project a text field which displays text in a text view. I have got mostly the coding for it to work, but it throws back two errors. The first one is
Cannot assign value of type '(UITextField) -> (UITextRange) -> String?' to type 'String?
This is after textView.text = mText in the enter button function. The second error is
Binary operator '+=' cannot be applied to operands of type 'String?' and '(UITextField) -> (UITextRange) -> String?'
after the textView.text += mText line. How can these problems be resolved?
import UIKit
class ShowGratitudeViewController: UIViewController {
#IBOutlet weak var textField: UITextField!
#IBOutlet weak var textView: UITextView!
#IBAction func enterTextButton(_ sender: Any) {
//gets text from text field
let mText = UITextField.text
//update previous text of textview
textView.text = mText
}
#IBAction func editTextButton(_ sender: Any) {
//gets text from text field
let mText = UITextField.text
//add text after previous text
textView.text += mText
}
}
You mistyped textField with UITextField. UITextField is a class and you can not get the text of the textField object from it.
Another error you have is += can not apply on an optional and a non-optional values. So unwrap it before applying this operator.
So the code would be like:
class ShowGratitudeViewController: UIViewController {
#IBOutlet weak var textField: UITextField!
#IBOutlet weak var textView: UITextView!
#IBAction func enterTextButton(_ sender: Any) {
//gets text from text field
let mText = textField.text
//update previous text of textview
textView.text = mText
}
#IBAction func editTextButton(_ sender: Any) {
//gets text from text field
let mText = textField.text
//add text after previous text
textView.text! += mText!
}
}
How to start a new line in UITextView with a little space, called paragraph I believe?
What you need to do is make the controller confront to UITextFieldDelegate
for example:
class ViewController: UIViewController,UITextFieldDelegate
{
//link the textfield
#IBOutlet weak var textField: UITextField!
override func viewDidLoad()
{
super.viewDidLoad()
// link the delegate to the textfield
textField.delegate = self
}
//this function detects the return button when it's pressed
func textFieldShouldReturn(_ textField: UITextField) -> Bool
{
//since we always want to start a new line with space we override the default function
textField.text += "\n "
return false
}
My save button is hidden with the function saveBtnHidden() in the code below. However, the save button won't reappear when text is typed into the text field. I have tried multiple solutions similar to this. Every time that I type into the text field, the save button just won't show up.
import UIKit
class TableViewController: UITableViewController, UITextFieldDelegate {
#IBOutlet weak var saveBtn: UIButton!
#IBOutlet var nicknameField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
saveBtnHidden()
}
func saveBtnHidden() {
if (nicknameField.text?.isEmpty ?? true) {
// is empty
saveBtn.isHidden = true
} else {
saveBtn.isHidden = false
}
}
#IBAction func saveBtnPressed(_ sender: Any) {
performSegue(withIdentifier: "nextPage", sender: nil)
}
}
You are getting this error because your function saveBtnHidden() is only called once in viewDidLoad(). It does not get called again when the text in your text field changes. To detect when text changes, you will need to add a target to your text field that calls a function when it changes (.editingChanged) like this:
nicknameField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged)
Then in the textFieldDidChange call your saveBtnHidden() function:
func textFieldDidChange(_ textField: UITextField) {
saveBtnHidden()
}
Code adapted from: How do I check when a UITextField changes?
Use delegate to be notify of any change. Delegates is a key part of iOS development and Apple's framework.
class TableViewController: UITableViewController, UITextFieldDelegate {
#IBOutlet weak var saveBtn: UIButton!
#IBOutlet var nicknameField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
saveBtnHidden()
nicknameField.delegate = self
}
func textFieldDidChange(_ textField: UITextField) {
saveBtnHidden()
}
// More of your source code below...
I'm trying to implement UITextFieldDelegate in separate class, but it didn't working:
class ViewController: UIViewController {
#IBOutlet var TextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
let restrictor = TextFieldRestrictController()
TextField.delegate = restrictor
}
}
class TextFieldRestrictController : NSObject, UITextFieldDelegate {
public func textField(_ textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool {
let inverseSet = NSCharacterSet(
charactersIn:"0123456789.").inverted
let components = string.components(separatedBy: inverseSet)
let filtered = components.joined(separator:"")
return string == filtered
}
}
But this is working:
class ViewController: UIViewController {
#IBOutlet var TextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
TextField.delegate = self
}
public func textField(_ textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool {
let inverseSet = NSCharacterSet(
charactersIn:"0123456789.").inverted
let components = string.components(separatedBy: inverseSet)
let filtered = components.joined(separator:"")
return string == filtered
}
}
Is there something wrong?
UITextField's .delegate is a weak property so at the end of viewDidLoad method,
restrictor will be deallocated because there is no other strong reference around that is pointing to the object which it points to.
You can try printing out ValidationTextField.delegate in viewDidAppear(animated:) and see it returns nil.
To overcome this problem, you can define restrictor as an instance variable so it'll stay alive as long as the view controller is alive:
class ViewController: UIViewController {
#IBOutlet weak var ValidationTextField: UITextField!
let restrictor = TextFieldRestrictController()
override func viewDidLoad() {
super.viewDidLoad()
ValidationTextField.delegate = restrictor
}
}
I have a button that is disabled in my view controller. I have IBActions for when two text fields are edited. I am trying to enable the button when two text fields both contain integers. I have tried to do this, but whenever I run the ios simulator, the button stays disabled even when I put integers into each text field. Why is it staying disabled? I am new to swift, so please help me out. Here is the code for my entire project:
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var calculatorButton: UIButton!
#IBOutlet weak var inspirationLabel: UILabel!
#IBOutlet weak var beginningLabel: UILabel!
#IBOutlet weak var calculatorContainer: UIView!
#IBOutlet weak var answer1Label: UILabel!
#IBOutlet weak var doneButton: UIButton!
#IBOutlet weak var yourWeightTextField: UITextField!
#IBOutlet weak var calorieNumberTextField: UITextField!
#IBOutlet weak var menuExampleButton: UIButton!
#IBOutlet weak var aboutButton: UIButton!
#IBOutlet weak var calculateButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib
yourWeightTextField.delegate = self
calorieNumberTextField.delegate = self
calculateButton.enabled = false
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func calculatorButtonTapped(sender: AnyObject) {
calculatorContainer.hidden = false
inspirationLabel.hidden = true
beginningLabel.hidden = true
menuExampleButton.hidden = true
aboutButton.hidden = true
}
#IBAction func yourWeightEditingDidEnd(sender: AnyObject) {
yourWeightTextField.resignFirstResponder()
}
#IBAction func calorieNumberEditingDidEnd(sender: AnyObject) {
calorieNumberTextField.resignFirstResponder()
}
var yourWeightFilled = false
var calorieNumberFilled = false
func yourWeightTextFieldValueValidInt(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
// Find out what the text field will be after adding the current edit
let text = (yourWeightTextField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)
if let intVal = text.toInt() {
self.yourWeightFilled = true
} else {
self.yourWeightFilled = false
}
return true
}
func calorieNumberTextFieldValueValidInt(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
// Find out what the text field will be after adding the current edit
let text = (calorieNumberTextField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)
if let intVal = text.toInt() {
self.calorieNumberFilled = true
} else {
self.calorieNumberFilled = false
}
return true
}
#IBAction func yourWeightTextFieldEdited(sender: AnyObject) {
if self.yourWeightFilled && self.calorieNumberFilled {
self.calculateButton.enabled = true
}
}
#IBAction func calorieNumberTextFieldEdited(sender: AnyObject) {
if self.yourWeightFilled && self.calorieNumberFilled {
self.calculateButton.enabled = true
}
}
}
Your delegate methods are a bit mixed up -- they have to be named exactly what the caller expects, or they won't be found, so yourWeightTextFieldValueValidInt() and calorieNumberTextFieldValueValidInt() aren't being called at all. Instead you'll need to handle the edits to both text fields in a single method:
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
// Find out what the text field will be after adding the current edit
let text = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)
if textField == yourWeightTextField {
yourWeightFilled = text.toInt() != nil
} else if textField == calorieNumberTextField {
calorieNumberFilled = text.toInt() != nil
}
return true
}