How to clear multiple textviews upon Editing? - ios

I am trying to clear multiple textviews on editing. I know how do so with one textView (IE):
class ViewController: UIViewController, UITextViewDelegate {
#IBOutlet weak var myTextView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
myTextView.delegate = self
}
func textViewDidBeginEditing(textView: UITextView) {
myTextView.text = ""
}
How would I use the same concept for multiple textviews?

func textViewDidBeginEditing(textView: UITextView) {
myTextView.text = ""
}
The above delegate method will get called when a text view begins editing. And this method holds the reference to the textView that called in the textView object. You can use that reference to clear the text instead of using a separate reference/outlet to the textView.
So the method would be:
func textViewDidBeginEditing(textView: UITextView) {
textView.text = ""
}
From the Documentation:
Description:
Tells the delegate that editing began in the specified text field.
This method notifies the delegate that the specified text field just
became the first responder. Use this method to update state
information or perform other tasks. For example, you might use this
method to show overlay views that are visible only while editing.
Implementation of this method by the delegate is optional.
Parameters:
textView
The text view in which an editing session began.

Related

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.

Is there a callback for setting text in a UITextField in code?

I want to detect if a UITextField's text is set in code. e.g. I need a callback for someTextField.text = "Some Text". I don't want to register the notification for .editingChanged as this will also be called every single time the user types something. It should only be called when the value is set in code.
Is there a way to do this? Any pointers would be greatly appreciated! Thanks!
You can check with the textfields .isEmpty method so
if someTextField.isEmpty {
//do something
}
You can override the text var in UITextField by subclassing
class ObservableTextField: UITextField {
var action : (()->Void)?
override var text: String?{
didSet{
action?()
}
}
}
Use
#IBOutlet weak var obsTextField: ObservableTextField!
override func viewDidLoad() {
super.viewDidLoad()
obsTextField.action = {
debugPrint("changed")
}
}

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."

(Swift) UITextView not displaying text

I'm making a text-based iOS game which uses a single view consisting of a UITextView (scrollable, not editable) and a UITextField. I've made it so when I press return while editing the textField, the keyboard closes and the text of the textField is added to the textView. However, the text of the UITextView doesn't appear at all. The background color still appears, but nothing else, no matter how I try to display it. I've already tried setting the font size and color.
Here's code from the ViewController that handles both UI components.
import UIKit
class ViewController: UIViewController, UITextFieldDelegate, UITextViewDelegate {
// outlets / actions
#IBOutlet weak var outputView: UITextView!
#IBOutlet weak var inputField: UITextField!
var uni: Universe? // a custom class that contains the game's data
override func viewDidLoad() {
//outputView.addObserver(self, forKeyPath: "contentSize", options: NSKeyValueObservingOptions.New, context: nil)
inputField.delegate = self
outputView.delegate = self
inputField.text = "press return for help"
outputView.text = ""
outputView.textColor = UIColor.greenColor()
outputView.frame = self.view.frame
// The next 3 lines make a new Universe object.
uni = Assembler.build(outputView)
uni!.setUni()
uni!.setParser()
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
uni!.player.viewLocation()
}
// delegate method; this should do 3 things:
// 1. remove the keyboard
// 2. call uni.parser.read(text)
// 3. remove the text in the field
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
outputView.text! += textField.text! + "\n"
uni!.parser!.read(textField.text!) // This function interprets the text from textField and prints something appropriate in the textView.
textField.text = ""
return true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// The rest of the code makes the whole frame shift up/down when the keyboard appears/disappears to keep the UITextField visible.
}
Any help at all would be greatly appreciated. The similar questions on this site haven't given me anything to go on.

How to make a UITextView that selects a word upon a single touch?

I have a UITextView that is not editable but needs to be able to select a word upon a single touch of that word and have the selected word be passed on to another function. What's a way to go about this? Any help would be appreciated.
Superhacky solution (if you have a lot of words this is a bad bad idea):
Make all words in UITextView links (but don't format them as such).
Make your UITextView selectable in IB
Have your VC (or whoever owns the UITextVeiw) to implement UITextViewDelegate
Implement -(BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange
Use the characterRange to set UITextView selectedTextRange
Profit!
Less hacky solution would be to use a UITapGestureRecognizer to get the tap location, translate it to UITextView and select the glyphs that horizontally surrond the tap location.
Step 1:
To get the selected string from textView, you have to implement UITextViewDelegate delegate and implement a method.
Step 2:
pass the selectedText to another function
class ViewController: UIViewController, UITextViewDelegate {
#IBOutlet weak var textView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.textView.delegate = self;
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func textViewDidChangeSelection(textView: UITextView) {
let range: NSRange = textView.selectedRange
let text = textView.text as NSString
let selectedText = text.substringWithRange(NSMakeRange(range.location, range.length))
self.getSelectedText(selectedText)
}
func getSelectedText(text: String) {
NSLog("\(text)")
}
}

Resources