UItextView delegate not called using custom keyboard - iphone

I have several UITextView subviews, all using the same custom input interface (basically a numberpad with an autofill-option and a save button).
My problem is that the delegate method shouldChangeCharactersInRange: is not called when the textfield's text is modified from my custom keyboard (it does work when pasting text from clipboard into the textfields and also when using the standard numberpad keyboard). The text of the textfields change, but the delegate method to prevent invalid entries is not called. Other delegate methods of style DidBeginEditing: are called always.
despite of what is said in this SO LINK the documentation states that the shouldChangeCharactersInRange: delegate method will be called: "The text view calls this method whenever the user types a new character or deletes an existing character."
What am I missing?
relevant code parts:
ViewController.h:
#interface ManualPositionViewController : UIViewController <UITextFieldDelegate> {
LocationEntryTextField *latitude;
}
#property (nonatomic, retain) IBOutlet LocationEntryTextField *latitude;
#property (nonatomic, retain) IBOutlet LocationKeyboard *locationKeyboard;
..
ViewController.m:
#synthesize latitude;
#synthesize locationKeyboard;
self.latitude.inputView = locationKeyboard;
self.latitude.delegate = self;
- (void)textFieldDidBeginEditing:(LocationEntryTextField *)aTextField {
NSLog(#"textFieldDidBeginEditing called!");
self.locationKeyboard.currentTextfield = aTextField;
}
- (BOOL)textField:(LocationEntryTextField *)editedTextField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)replacementString {
NSLog(#"shouldChangeCharactersInRange called!");
NSCharacterSet *decimalSet = [NSCharacterSet decimalDigitCharacterSet];
if ([[replacementString stringByTrimmingCharactersInSet:decimalSet] isEqualToString:#""]) {
NSLog(#"Result: YES");
return YES;
}
else {
NSLog(#"Result: NO");
return NO;
}
}
LocationKeyboard.h:
#import <UIKit/UIKit.h>
#import "LocationEntryTextField.h"
#interface LocationKeyboard : UIView {
LocationEntryTextField *currentTextfield; // track first responder
}
#property (weak) LocationEntryTextField *currentTextfield;
- (IBAction) numberButtonPressed:(UIButton*)sender;
- (IBAction) backspaceButtonPressed:(UIButton*)sender;
#end
- (IBAction) numberButtonPressed:(UIButton*)sender {
NSString *entryString = #"test";
[self.currentTextfield replaceRange:self.currentTextfield.selectedTextRange withText:entryString];
}
LocationEntryTextField.h:
#interface LocationEntryTextField : UITextField
..

This line:
[self.currentTextfield replaceRange:self.currentTextfield.selectedTextRange withText:entryString];
doesn't result in a call to textField:shouldChangeCharactersInRange:replacementString:. Is that what you are expecting?
Since you are explicitly changing the text of the text field, there is no "typing" going on.
The proper way to have your custom keyboard update the text field is to call the 'insertText:` method. This method will properly deal with any selection, moving the cursor, and calling delegate methods.
Edit: You may wish to look at my answer here for a complete custom keyboard setup (minus the actual buttons).

Related

UITextView did end editing

I would like to NSLog something when my UITextView is done editing.
I've tried
- (BOOL)textViewShouldEndEditing:(UITextView *)textView
and
- (void)textViewDidEndEditing:(UITextView *)textView
neither worked.
fix:
myTextView.delegate = self;
do you set the delegate of your textview?
fix:
set delegate in .h file like this:
#import <UIKit/UIKit.h>
#interface TextViewController : UIViewController <UITextViewDelegate>
{
UITextView *textView;
}
#property (nonatomic, retain) UITextView *textView;
#end
If you are using UITextField instead make sure to use UITextFieldDelegate and not UITextViewDelegate. And this method instead, that fixed my problems.
- (void)textFieldDidEndEditing:(UITextField *)textField

IOS setting a custom delegate

I'm working through the IOS HelloWorld example and I have a question regarding setting the delegate for a TextField. In the example it was as easy as control-dragging from the TextField to the ViewController. But now say I wanted to create a custom class to act as my delegate as so:
#import <Foundation/Foundation.h>
#interface SweetAssDelegate : NSObject <UITextFieldDelegate>
- (BOOL)textFieldShouldReturn:(UITextField *)theTextField;
#end
#import "SweetAssDelegate.h"
#implementation SweetAssDelegate
- (BOOL)textFieldShouldReturn:(UITextField *)theTextField
{
NSLog(#"Calling Delegate");
[theTextField resignFirstResponder];
return YES;
}
#end
How can I set this class to be the delegate of the TextField? As far as I can tell there is not way to accomplish this through the GUI. I tried manually setting the delegation after window load with no success:
#import "ViewController.h"
#import "SweetAssDelegate.h"
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UITextField *inputField;
#end
- (void)viewDidLoad
{
[super viewDidLoad];
SweetAssDelegate *foo = [[SweetAssDelegate alloc] init];
[self.inputField setDelegate:foo];
NSLog(#"Delegate: %#", self.inputField.delegate);
}
I actually receive some sort of memory exception when bringing up the keyboard? Any ideas? Thanks.
As a side question, where should I always use viewDidLoad to initialize any variables? I noticed that init was not being called???
Your delegate object, foo, is allowed to fall out of scope and is released at the end of viewDidLoad and by the time the keyboard comes up, it doesn't exist anymore. Make it an ivar (or property) of your view controller, or otherwise make sure that foo doesn't fall out of scope at the end of viewDidLoad.
Thus, it could be something like:
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UITextField *inputField;
#property (strong, nonatomic) SweetAssDelegate *foo;
#end
- (void)viewDidLoad
{
[super viewDidLoad];
self.foo = [[SweetAssDelegate alloc] init];
[self.inputField setDelegate:self.foo];
NSLog(#"Delegate: %#", self.inputField.delegate);
}
Your textfield delegate must have the implemented to be your textfield delegate I guess.
A delegate manages the communication between objects, which means your custom delegate must allow communication between objects and must provide methods, the textfield can work with...
Another example is a tableView:
You can make a custom delegate which implements the delegates and then calls some tableview related Methods...
Here this code might be interesting for you:
#interface myCustomDelegateForTextFields <UITextFieldDelegate>
#end
#implementation myCustomDelegateForTextFields
- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
return TRUE;
}
#end
#implementation ViewController
myCustomDelegateForTextFields *txtfielddelegate = [[myCustomDelegateForTextFields alloc] init];
UITextField *whatever;
whatever.delegate = txtfielddelegate;
//your textfield now listens to the BOOL method in your custom delegate
#end
Is it that what u were looking for? :)
you can ofc pack the myCustomDelegateForTextField delegate in another class and call the class

UITextField crashes if changing text in editing changed

I wrote a simple ios5 application (includes garbage collector) that has a single view and a UITextField
I need to analyze input text in this UITextField
here's my code.
header file:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController<UITextFieldDelegate>
{
IBOutlet UITextField *myTextField;
}
#property (nonatomic, retain) IBOutlet UITextField *myTextField;
-(IBAction)editingChanged:(UITextField *)sender;
editingChanged: tracked with send event editing changed so this method calls everytime user changes something in my UITextField
part of implementation file:
#pragma mark - textField
-(NSString *)stringWithoutAbc:(NSString *)sourceString
{
NSString *resultString=[sourceString stringByReplacingOccurrencesOfString:#"abc:" withString:#""];
if (![resultString isEqualToString:sourceString])
{
NSLog(#" sourceString: %#", sourceString);
NSLog(#" resultString: %#", resultString);
};
return resultString;
}
-(IBAction)editingChanged:(UITextField *)sender
{
NSLog(#"editing Changed. text: %#", sender.text);
//removing "abc:" from string in text field
NSString *str=[self stringWithoutAbc:sender.text];
//if something was removed - changing text in text field
if (![str isEqualToString:sender.text])
{
sender.text=str;
};
}
Everytime user changes text in UITextField we remove "abc:" strings from this text using standard NSString method.
The problem is: the application is unstable. It sometimes crashes when "abc:" gets removed.
Help me please. How to solve this problem?
You can use below textField's delegate method :-
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
If you are using Arc, you don't have to retain the object. And btw, ARC is not garbage collector.
http://longweekendmobile.com/2011/09/07/objc-automatic-reference-counting-in-xcode-explained/
MAybe because you use retain on the textField.

UITextView hide keyboard in iphone

I want to hide keyboard when a user presses return in UITextView object in iphone. However, mysteriously this is not working for UITextView but working for UITextField. I am unable to figure out why...
This is what I did:
1) I created a view based application in XCode4.
2) in .xib created UITextView, UITextField and UIButton objects
3) Marked both UITextField and UITextView delegates to File's Owner in Outlets
4) Added <UITextFieldDelegate> to #interface UIViewController in .h
5) Added textFieldShouldReturn function in .m
Here are the codes:
.h file
#interface keyboardDisappearViewController : UIViewController <UITextFieldDelegate>
{
UITextView *textBoxLarge;
UITextField *textBoxLittle;
}
#property (nonatomic, retain) IBOutlet UITextView *textBoxLarge;
#property (nonatomic, retain) IBOutlet UITextField *textBoxLittle;
- (IBAction)doSomething:(id)sender;
#end
.m file
- (BOOL) textFieldShouldReturn:(UITextField *)theTextField
{
NSLog(#"textFieldShouldReturn Fired :)");
[textBoxLarge resignFirstResponder];
[textBoxLittle resignFirstResponder];
return YES;
}
Amazingly, the keyboard is disappearing in case of textBoxLittle (UITextField) but not in case of textBoxLarge(UITextView)
As a further check I, made the button to call function doSomething
- (IBAction)doSomething:(id)sender {
[textBoxLarge resignFirstResponder];
[textBoxLittle resignFirstResponder];
}
When I am pressing the button, keyboard is disappearing in both textboxes.
Its driving me nuts why textFieldShouldReturn is working for small textbox, but NOT for large textbox.
Please Help!
Three things:
Make your view implement UITextViewDelegate.
#interface keyboardDisappearViewController : UIViewController
<UITextFieldDelegate, UITextViewDelegate>
Add the following method:
- (BOOL)textView:(UITextView *)textView
shouldChangeTextInRange:(NSRange)range
replacementText:(NSString *)text
{
if ([text isEqualToString:#"\n"])
{
[textView resignFirstResponder];
}
return YES;
}
Set the file's owner as delegate for the UITextView in the interface builder.
(BTW: Solution copied from the comments to the previous answer, as it took me a while to extract. I though others could benefit from my experience.)
You need to write code in UITextViewDelegate and assign it to your class.
Simple trick
Set delegate for your text view and then
doSomething
{
}
action connect to ext view for control event didEndOnExit and tuchupinside
// To dismiss key board when user clicks enter/return
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
if([text isEqualToString:#"\n"])
{
[textView resignFirstResponder];
return NO;
}
return YES;
}
Use this code
Inherit UITextViewDelegate protocol in your Viewcontroller add the text
#interface YourViewController () <UITextViewDelegate>
In viewDidLoad set yourself as a delegate:
yourUITextView.delegate = self;
Implement the delegate method below:
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
return NO;
}
Key Points
Someone needs to be listening for the Return Key press
UITextFieldDelegate
textFieldShouldReturn(textField : UITextField)
Someone needs to manually dismiss the keyboard
resignFirstResponder()
#1: Create a UITextFieldDelegate and assign it as the delegate to your UITextField -
exampleTextField.delegate = yourUITextFieldDelegate;
#2: Have 'yourUITextFieldDelegate' contain the following -
func textFieldShouldReturn(textField : UITextField) -> Bool {
self.titleField.resignFirstResponder(); //Here's the key!!!!!
return true; //true just says 'default behavior'
}
If you came here looking for the Swift solution, like I did, here you are :)
extension keyboardDisappearViewController : UITextViewDelegate {
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
if(text == "\n") {
textView.resignFirstResponder()
}
return true
}}
You have coded in the .h file:
#interface keyboardDisappearViewController : UIViewController <UITextFieldDelegate>
{
UITextView *textBoxLarge;
UITextField *textBoxLittle;
}
#property (nonatomic, retain) IBOutlet UITextView *textBoxLarge;
#property (nonatomic, retain) IBOutlet UITextField *textBoxLittle;
- (IBAction)doSomething:(id)sender;
#end
It should be:
#interface keyboardDisappearViewController : UIViewController <UITextFieldDelegate>
{
UITextView *textBoxLarge;
UITextField *textBoxLittle;
}
#property (nonatomic, retain) IBOutlet UITextField *textBoxLarge;
#property (nonatomic, retain) IBOutlet UITextField *textBoxLittle;
- (IBAction)doSomething:(id)sender;
#end

UITextView in tableHeaderView can't find delegate

I have a UITableView tableHeaderView defined in a nib file. The tableHeaderView contains a UITextView. The UITextView's delegate is set to the UITableViewController and the UITableViewController supports the UITextViewDelegate protocol. The UITableViewController is setting various properties in the tableHeaderView including the UITextView's text and that all works fine. But textFieldShouldReturn:(UITextField *)textField in the UITableViewController never gets called and I can't get the keyboard to close after I've tapped the UITextView.
I've tried every suggestion I can find in the docs and various posts, but no luck. None of the examples I've found have this specific case of a UITextView inside a tableHeaderView.
Is there something special I need to do. Has anyone done this successfully?
I've tried setting the UITextView delegate in code, but no luck.
#class Decision;
#interface DecisionDetailViewController : UITableViewController <UINavigationControllerDelegate, UITextViewDelegate> {
Decision *decision;
UIView *tableHeaderView;
UITextView *nameTextField;
}
#property (nonatomic, retain) Decision *decision;
#property (nonatomic, retain) IBOutlet UIView *tableHeaderView;
#property (nonatomic, retain) IBOutlet UITextView *nameTextField;
#end
#implementation DecisionDetailViewController
#synthesize decision;
#synthesize tableHeaderView;
#synthesize nameTextField;
- (void)viewDidLoad {
self.navigationItem.rightBarButtonItem = self.editButtonItem;
if (tableHeaderView == nil) {
[[NSBundle mainBundle] loadNibNamed:#"DecisionDetailHeader" owner:self options:nil];
self.tableView.tableHeaderView = tableHeaderView;
}
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[nameTextField resignFirstResponder];
return YES;
}
textFieldShouldReturn is a method of UITextFieldDelegate and not UITextViewDelegate. Thats probably your problem.