So I really am sorry if my post is a little off, this is my first time asking question.
I have a subclass of UITextView, let's call it A.
class A: UITextView{
var customDelegate: CustomTextViewDelegate!
}
extension A: UITextViewDelegate{
func textViewDidChange(_ textView: UITextView){
if let delegate = customDelegate{
delegate.textViewDidChange(textView)
}
}
func textViewShouldChangeTextIn(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if let delegate = customDelegate{
return delegate.textViewShouldChangeTextIn(baseTextView: textView, range: range, text: text)
}
return true
}
}
protocol CustomTextViewDelegate{
func textViewDidChange(_ customTextView: UITextView)
}
class SecondVC: UIViewController{}
extension SecondVC: CustomTextViewDelegate{
func textViewShouldChangeTextIn(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool
return false //this is where the problem is
}
As you can see, A delegate UITextViewDelegate to itself. I instantiate A to two different ViewController. in FirstVC, textViewDidChange method from the delegate is getting called normally, but on the secondVC it does not.
Now, here is the problem, any other method from UITextViewDelegate is getting called normally on SecondVC like textView(ShouldChangeTextIn), textViewDidEndEditing. Do anyone know what is going on? and where the problem could come from?
I have tried to make sure that not a single line of code try to assign the textViewDelegate to other class.
I have found the issue, I want to simplify things when I made this post by not mentioning quite few things. But, let's just say that I make CustomTextViewDelegate so that whatever VC instantiate the A (CustomTextView) can still implement their own custom "UITextViewDelegate". The problem lies when SecondVC TextView(shouldChangeText in) from CustomTextViewDelegate return false, therefore TextViewDidChange is not getting called.
Related
I realize this is a trivial question with tons of answer on SO. I may just need a pair of fresh eyes as I've triple checked everything and cannot see where I am going wrong with this. I just want to dismiss the keyboard on hitting the return key. I'm setting the delegate properly and implementing the proper methods, so why won't the keyboard dismiss?
Does having a collectionView in the viewController complicate things? (text field is NOT inside collectionView)
class SearchController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UITextFieldDelegate {
#IBOutlet weak var searchBar: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
searchBar.delegate = self
setupUI()
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
searchBar.resignFirstResponder()
return true
}
Things I've tried:
cleaning the project
restarting xcode
changing the searchBar.resignFirstResponder() to textField.resignFirstResponder()
setting the delegate for the text field inside IB instead of in viewDidLoad
What the heck am i missing here!?
You need to implement the proper text field delegate method. There is no such delegate method as textFieldShouldReturn(textField:). The proper method is textFieldShouldReturn(_:).
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
searchBar.resignFirstResponder()
return false
}
The _ makes a huge difference. You may have copied an old Swift 2 implementation.
It's best to let Xcode perform code completion to ensure you get the correct signature of any method you are implementing or calling.
Use this code
view.endEditing(true)
I have a UIImage next to a text field. I want the image to change (to a check) if the text field passes a format test. So, if there are six characters entered, the image will change. I tried to use textFieldDidChange but I think this function only gets called once the field changes the first time. Is there a function I can use that gets called every time a character is entered? Is there a better way to do it?
Use an action on the editing changed event. This can be accomplished through an IBAction or by adding a target manually.
IBAction
Add this method in your view controller and connect the outlet to the editingChanged event in your xib or storyboard:
#IBAction func textFieldChanged(_ sender: UITextField) {
// Your code here
}
Add Target
override func viewDidLoad() {
super.viewDidLoad()
yourTextField.addTarget(self, action: #selector(textFieldChanged(_:)), for: .editingChanged)
}
func textFieldChanged(_ sender: UITextField) {
// Your code here
}
According to Apple's documentation. Under the Discussion section, it says,
The text field calls this method whenever user actions cause its text to change. Use this method to validate text as it is typed by the user.
"This method" refers to textField(_:shouldChangeCharactersIn:replacementString:)
This is the full method:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
<code>
}
I found related questions and answers in objective-c but I couldn't find a proper way to this with swift? Is there methods to detect for text view same as text filed in swift?
I want to solve the issue hiding text view by keyboard. For that I need a way to detect start and end edit text view.
Any help would be appreciated.
Note: I'm using swift 3.
Just as Bawpotter said, "Use the delegate methods for UITextView". Here is what they look like in Swift 3:
func textViewDidBeginEditing(_ textView: UITextView) {
// Run code here for when user begins type into the text view
}
func textViewDidEndEditing(_ textView: UITextView) {
// Run code here for when user ends editing text view
}
Also make sure your UITextView's delegate is set to self or wherever these methods are in your app
Conform your ViewController class to UITextViewDelegate and then write
textView.delegate = self in your viewDidLoad(). After that write delegate methods for your textView as:
func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
// your code here
}
func textViewDidBeginEditing(_ textView: UITextView) {
// your code here
}
func textViewShouldEndEditing(_ textView: UITextView) -> Bool {
// your code here
}
func textViewDidEndEditing(_ textView: UITextView) {
// your code here
}
The following triggers when the Done button is clicked on the keyboard. It goes into the conditional and returns false. However, the keyboard remains on the screen.
class MyViewController: UIViewController, UITextViewDelegate{
func textView(textView: UITextView!, shouldChangeTextInRange: NSRange, replacementText: NSString!) -> Bool {
if(replacementText.isEqualToString("\n")) {
textBox.resignFirstResponder()
return false
}
return true
}
textBox is a delegate for the view. I have connected this through Interface Builder. Any ideas why it isn't dismissing the keyboard?
First of all please ensure that your My ViewController is a delegate of the textField,
And then, on the method shouldChangeTextInRange use the textView that is passed in the delegate method instead of your property textBox.
For example:
class MyViewController: UIViewController, UITextViewDelegate{
func viewDidLoad(){
super.viewDidLoad()
textBox.delegate = self
}
func textView(textView: UITextView!, shouldChangeTextInRange: NSRange, replacementText: NSString!) -> Bool {
if(replacementText.isEqualToString("\n")) {
textView.resignFirstResponder()
return false
}
return true
}
I am having trouble dismissing the keyboard of a text view in swift.
I was able to dismiss a textfield with the following
#IBAction func DismissKeyboard(sender: AnyObject)
{
self.resignFirstResponder()
}
But I'm not sure how I go about it with a text view
You have to set the textview.delegate to self and use the shouldChangeTextInRange function to resign on pressing return.
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
if text == "\n" // Recognizes enter key in keyboard
{
textView.resignFirstResponder()
return false
}
return true
}
swift 3
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if text == "\n" {
textView.resignFirstResponder()
return false
}
return true
}
just add the UITextView as an IBOutlet and use the same function:
#IBAction func DismissKeyboard(sender: AnyObject) {
yourtextView.resignFirstResponder()
}
This is a much better more-intuitive (for your user) solution for dismissing soft keyboard. The problem with the "\n" solution is the user cannot insert line-breaks in the textView-- as hitting the return/done button on the keyboard will dismiss the keyboard before the line break occurs. The method below lets you keep that functionality while teaching the user that just tapping outside text-entry fields is a standard way of dismissing keyboards.
// MARK: - dismiss keyboard when user taps outside of text boxes
override func viewDidLoad() {
super.viewDidLoad()
configureTapGesture()
}
private func configureTapGesture() {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(WriteJournalEntryViewController.handleTap))
view.addGestureRecognizer(tapGesture)
}
#objc func handleTap() {
view.endEditing(true)
}
(assumes this code is inside a UIViewController custom subclass named "WriteJournalEntryViewController).
view = your entire view in the UIViewController, so it works for more than just your textView object.
endEditing = a method for UIView class, you can read its documentation.