Unable to connect IBAction to UITextField in XIB (Swift) - ios

On one of my ViewControllers, I declared:
#IBOutlet var priceTextField : UITextField!
Then I tried to add the following based on the same UITextField:
#IBAction func priceTextFieldChanged(sender: UITextField) { updateOutput() }
When I looked at the XIB's File Owner and at the Received Actions, I was not able to connect the UITextField to this function for some reason. I even tried to drag that UITextField to the ViewController, but was not able to see the "Action" option. I checked the class. It's linked to the ViewController. Not sure what to do here.
Any advice?

A UITextField does not provide an action (sendAction:), that is why you can't hook-it-up.
What you need is to create a delegate, for textFieldDidBeginEditing or another delegate method of UITextField and set the UITextField delegate to your class instance.

#Zaph, something like this:
class ViewController: UIViewController,UITextFieldDelegate {
#IBOutlet var priceTextField : UITextField!
func textFieldDidEndEditing(textField: UITextField) {
if let value = sender.textIntegerValue() {
pricetepper.ifInRangeSetValue(value)
}
updateOutput()
}
}
Not sure if I pick the right method. Thanks.

Related

How to add countdown-timer to UIAlertController

I'm quite new to Swift and couldn't find any good explanation for this. I want the user to select a duration (h:m:s) when clicking on a UITextField in an alert and display the value in the textField.
Can someone please give me a hint or an explanation.
UITextField has delegate protocol called UITextFieldDelegate
in your viewController:
func viewDidLoad() {
super.viewDidLoad()
yourTextField.delegate = self
}
Conform your viewController to this delegate. There is a textFieldShouldBeginEditing method, it is called when the user taps into the textfield. You return false here, so the textField won't became first responder and the keyboard will not open and you can present your picker.
extension viewController: UITextFieldDelegate {
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
//open your alert here
openPicker()
return false
}
}
You can use UIPickerView to present to the user. You can read about that here and even create it based on the example:
explanation and example of UIPickerView

UITextView delegate methods not called

Swift beginner here. I am having quite a tough time getting my UITextView delegate methods to call. I have looked through many other questions, to no avail.
I have a UITextView set up in a ViewConroller. It looks like this:
There is a UIImageView directly above the UITextView, and everything is wrapped in a navigation controller, should be no big deal.
I made sure to connect the View from the storyboard to my ViewController:
From the storyboard I CTRL+Drag the UITextView right below the class declaration. This produces the line:
#IBOutlet weak var Description: UITextView!
Class declaration:
class ImageTextViewController: UIViewController, UITextViewDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
(I need the other delegates for my NavigationController and UIImageView)
I then declare the delegate as so:
override func viewDidLoad() {
super.viewDidLoad()
self.Description.delegate = self
Now the following delegate method should be called when I finish editing the UITextView. But for some reason it is not firing!
private func textViewDidEndEditing(_ textView: UITextView) -> Bool{
print("we are done editing")
spotDescription.resignFirstResponder()
return true
}
How do I get that to fire properly for my UITextView?
textViewDidEndEditing method do not have return value. You have to write this
func textViewDidEndEditing(_ textView: UITextView) {
print("we are done editing")
}
Jack is right.
In the image titled Storyboard Connection your viewController seems to be titled TextImageViewController, while in the class declaration example is titled ImageTextViewController.
The ViewController in the Storyboard and the ViewController should both be the same.
Андрей is also right.
TextViewDidEndEditing method does not have a return value.
lindanordstrom also makes a good point:
TextViewDidEndEditing shouldn't be private.

Changing label text to what user inputs into UITextField

This is a very basic question but I'm not sure what the problem is. I'm trying to make a simple "hello world" program where the user inputs what they want into the textfield and whatever they enter goes into the label. However, nothing seems to be happening and I'm unsure why since my push function worked exactly how I expected it to.
import UIKit
class ViewController: UIViewController {
#IBOutlet var PopUp: UITextField!
#IBOutlet weak var HelloWorld: UILabel!
#IBAction func Push(_ sender: UIButton) {
PopUp.isHidden = false
PopUp.text = "hello World"
}
#IBAction func send(_ sender: UITextField) {
HelloWorld.text = sender.text
}
}
Based on the code you provided, func send is an unknown to me, as to whether or not it is even firing. func send might be called, might not, either way, it is strange to see a _ sender: UITextField for an IBAction.
What event are you firing related to the UITextField? Are you trying to update your HelloWorld UILabel as the user types in the UITextfield?
To update your UILabel with whatever has been typed in your UITextField, you just need a UIButton Touch Up Inside IBAction. I think you can delete IBAction func send completely, unless you are trying to update the UILabel as the user types in the UITextField. Make sure you remove the IBAction Outlet from your Storyboard if I am correct about this point.
Based on the code you provided the Push func does not set text in your UILabel. I am assuming Push is an UIButton Touch Up Inside IBAction. You can set your HelloWorld UILabel text, in func Push, you do not need to use the sender of the event, try this and you will see the HelloWorld UILabel text populated:
#IBAction func Push(_ sender: UIButton) {
//PopUp.isHidden = false //why are you doing this? the UITextField PopUp should already be visible if you are typing text into it, so this code is superfluous as the value of PopUp.isHidden is already false
HelloWorld.text = PopUp.text
PopUp.text = "hello World"
}
If you are trying to have your UILabel display the text as you type into the UITextField you should clarify your question. And if it is the case you will need to make your UIViewController a UITextFieldDelegate
Here is the one way of approach :
override func viewDidLoad() {
super.viewDidLoad()
PopUp.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged) // when textfield is edited this will call
}
func textFieldDidChange(_ textField: UITextField) {
HelloWorld.text = textField.text
}

Delegate of TextField

I faced something and I cannot understand it.
In the tutorial which I watched, instructor press (cntrl + click) delegate option and drag it into ViewController class. Then, textfield options become like the photo. I searched for a lot and I found an explanation ,but I couldn't understand it exactly.
Explanation : To be able to use UITextFieldDelegate methods, ViewController class must adopt this protocol. However, before using any method, we have to choose this delegate option.
I cannot understand this option. What is the benefit of it ?
so in order to use it and understand it try out these steps:
1 adopt UITextFieldDelegate protocol to your class like so
class MyViewController: UIViewController, UITextViewDelegate {
2 implement callback methods for the UITextViewDelegate. For example:
//MARK: UITextViewDelegate
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
print(textField.text ?? "")
return true
}
These methods are made for managing and validating text from the TextView.
Maybe you should read about protocols.
Or if you don't understand why you are setting your delegate form the storyboard directly it's because this way you will not have an extra property declared in your class. I will be done seamlessly and you will not have this in your class:
#IBOutlet weak var myTextField: UITextField!
//...
override func viewDidLoad() {
super.viewDidLoad()
myTextField.delegate = self
}
First add delegate to your view controller as
UITextFieldDelegate
Only then the delegate functions can be used in the view controller.
And for the functions to work as expected,
You have to set the textfield's delegate as self. Eg
textfield.delegate = self
Setting the delegate of textfield as self is the programatic way of doing the same thing the instructor did (as you said).

How to get the UITextField's delegates events while subclassing it, without losing the delegation if the user of it set itself as the delegate?

For simplicity, let's say I want to create a custom UITextField and I want to add a simple behaviour to it; Which is, if the textfield becomes the first responder, the background color would be changed to green.
To do so, in my custom class I have to set the class as the delegate to receive the event of becoming first responder. But the thing is that if the user of this custom textfield set itself as the delegate the events are not sent to the custom textfield(Since only one object can be the delegate of another object)
I can manually forward all the events, but I'm looking for a cleaner and more scalable solution.
Here's a sketch of the situation:
class MyTextField: UITextField {
override func awakeFromNib() {
super.awakeFromNib()
delegate = self
}
}
extension MyTextField: UITextFieldDelegate {
func textFieldDidBeginEditing(textField: UITextField) {
backgroundColor = UIColor.greenColor()
}
}
but if the user of MyTextField do this:
class ViewController: UIViewController {
#IBOutlet weak var myTextField: MyTextField!
override func viewDidLoad() {
super.viewDidLoad()
myTextField.delegate = self
}
}
the behaviour won't work; because the delegation relationship to MyTextField is gone.
NOTE: I'm not only interested in becoming first responder problem, rather it's about using any methods of the delegate, with capability of the user of my custom UITextField setting itself as the delegate, at the same time.
Thanks, in advance.
As you say, most delegation is restricted to a single object as the delegate.
Since a text field is a responder, you should be able to override func becomeFirstResponder() -> Bool to change the color, while letting the user of the object handle the delegation as it expects.
UIResponder docs: "Subclasses can override this method to update state or perform some action such as highlighting the selection."

Resources