In my interface I have:
#interface MainViewController : UIViewController <SKProductsRequestDelegate, SKPaymentTransactionObserver, UITextFieldDelegate> {
UITextField *Stock;
// ....
}
This is the implementation I have:
- (BOOL)Stock:(UITextField *)textField shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
if([[textField text] isEqualToString:#"\n"]) {
[textField resignFirstResponder];
return NO;
}
return YES;
}
In the viewDidLoad I have Stock.delegate = self;
I am expecting this method is called after any character is typed in the text field. But this routine is never called. What is the problem?
Thanks
If this is a UITextField, you've just implemented a random method. The actual delegate method is
-textField:shouldChangeCharactersInRange:replacementString:
Try providing that one.
Did you wire the TextField (Stock in your case) Delegate to FileOwner ?
If not then try this in viewDidLoad method of the Controller
Stock.delegate = self;
Or you can just wire it in IB.
Declare MainViewController conforming UITextFieldDelegate:
#interface MainViewController : UIViewController < UITextFieldDelegate >
To be called this method of UITextFieldDelegate should be declared as:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
In code or in IB MainViewController should be set to be delegate.
Correct and it will be fired as supposed.
Related
I must be doing something fundamentally wrong, my implementation methods for the UITextViewDelegate aren't firing. I have a UITextView that is a subview of a UITableCellView and the delegates aren't being called.
- (void)textViewDidBeginEditing:(UITextView *)textView {
NSLog(#"textViewDidBeginEditing");
// never called...
}
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
NSLog(#"shouldChangeTextInRange");
// never called...
}
Suggestions? I don't know whether it matters, but the protocol is explicitly named in my #interface declaration.
#interface DetailViewController () <UITextViewDelgate, ..., ....>
Thanks!
You should add the textViewObj.delegate = self or give delegate connection for that text view property in xib file, then it should work and fire all delegate methods of UITextView.
Couple of pointers on this based on my experience:
1) Check whether you are using a UITextField or a UITextView.
2) Based on the type of text field you are using add the following declaration to your interface declaration
#interface MyInterface : UIViewController<UITextFieldDelegate>
or
#interface MyInterface : UIViewController<UITextViewDelegate>
3)Register your controller as the delegate for your text field:
[myTextField setDelegate:self];
4)Override the desired method which being
-(void)textFieldDidBeginEditing:(UITextField *)textField
or
- (void)textViewDidBeginEditing:(UITextView *)textView;
in my case.
I want to subclass UITextField and have a method that sets the maximum number of characters. allowed. In the init method of this subclass I try setting the inputDelegate to self but the callbacks aren't triggered. Also this is an iOS 5 thing only. My question is what protocol or notification would allow me to fire an event when a key is tapped so that I don't have to implement the UITextField delegate in my view controller to achieve this limit.
Thanks.
You could do it like this, create a delegate class for you textfield
.m file
#implementation LimitedTextFieldDelegate
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if(textField.text.length >= 5 && ![string isEqualToString:#""])
return NO;
return YES;
}
#end
.h file
#interface LimitedTextFieldDelegate : UITextField<UITextFieldDelegate>
#end
in the UITextField subclass do the following
- (id)init
{
self = [super init];
if (self) {
//limitedDelegate is a property of your textfield subclass
self.limitedDelegate = [[LimitedTextFieldDelegate alloc] init];
self.delegate = self.limitedDelegate;
}
return self;
}
I've subclassed a UITextField and I'd like to use a method similar to textField:shouldChangeCharactersInRange:replacementString: inside the subclass to get notified when a character is typed and if necessary block the change, but avoid setting the fields delegate to itself.
I've found if I override keyboardInput:shouldInsertText:isMarkedText: and keyboardInputShouldDelete: I can get the desired effect, unfortunately these methods are private and anything using the class won't make it through the App Store submission process.
Anyone know of a public method that achieves the same thing and doesn't require the field being its own delegate?
UPDATE:
I went with the suggestion of creating a separate object just to be the delegate, which itself can have a delegate to forward messages to.
Having tried to subclass UITextField before, I've since learned to avoid that and go the delegate route instead (it has a similar method called - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string that should do what I think you've described).
One strategy to explore here is to override the setDelegate: method and then do some message forwarding. You can use [super setDelegate: self] to make sure your calls gets first dibs at the delegate messages. In your override of setDelegate: set an internal ivar, e.g.
- (void) setDelegate: (id<UITextFieldDelegate>) internalDelegate;
{
[setInternalDelegate: internalDelegate];
}
Then for each of the the UITextField delegate methods do your thing before forwarding on the delegate message, e.g.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;
{
// do your thing with range and replacement string
// now forward message on the 'other' delegate
[[self internalDelegate] textField: self shouldChangeCharactersInRange: range replacementString: string];
}
Typically, you'll want to override all of the delegate methods, even if for most of them all you do is a straight forward.
Update You note in comments that the forwarding approach is raising issues. If so, then traditional delegation is the way to go. (And, in generally, it is the way to go - although I've used forwarding delegate once or twice, I'm not sure if, with hindsight, it was absolutely essential and I've not checked to see if I've done it with UITextField. #Scott Corscadden has and does not recommend it.)
The most common pattern is to make the ViewController that looks after the view in which the UITextField is a subview the delegate. You don't say in your answer if there's particular reason why you need to work with the subclass. If you're packing interesting stuff into the UITextField then it might be, though you could always another poster suggests and create a companion class for UITextField that does that work and use that as the delegate. In any case, if need be, you can always get the delegate object to call extra methods on your UITextField subclass, e.g.
// in the delegate object class
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;
{
[delegate doSomeExtraThingInTheTextFieldSubclassThatItSeemsToMakeSenseToDoThereRatherThanHere];
// maybe that's it, or maybe this object also wants to do something here...
}
You may play with Objective-C runtime to achieve this. The following code is working for me.
The idea is:
in subclass we set delegate property to self;
we override setDelegate: method in which we store supplied delegate to a variable (forwardDelegate);
by overriding respondsToSelector:, forwardInvocation: and methodSignatureForSelector: we either call method on self or forward it to saved forwardDelegate.
// MyTextField.h
#interface MyTextField : UITextField
#end
// MyTextField.m
#interface MyTextField () <UITextFieldDelegate>
#end
#implementation MyTextField {
id forwardDelegate;
}
- (void) myTextFieldCommonInit
{
[super setDelegate:self];
}
- (id) initWithCoder:(NSCoder *)coder
{
if ((self = [super initWithCoder:coder])) {
[self myTextFieldCommonInit];
}
return self;
}
- (id) initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame])) {
[self myTextFieldCommonInit];
}
return self;
}
- (void) setDelegate:(id)delegate
{
forwardDelegate = delegate;
}
- (BOOL) respondsToSelector:(SEL)selector
{
if ([super respondsToSelector:selector]) {
return YES;
} else {
return [forwardDelegate respondsToSelector:selector];
}
}
- (void) forwardInvocation:(NSInvocation *)invocation
{
if ([super respondsToSelector:[invocation selector]]) {
[super forwardInvocation:invocation];
} else if ([forwardDelegate respondsToSelector:[invocation selector]]) {
[invocation invokeWithTarget:forwardDelegate];
} else {
[self doesNotRecognizeSelector:[invocation selector]];
}
}
- (NSMethodSignature *) methodSignatureForSelector:(SEL)selector
{
NSMethodSignature *signature = [super methodSignatureForSelector:selector];
if (signature) {
return signature;
} else {
return [forwardDelegate methodSignatureForSelector:selector];
}
}
#pragma mark - UITextFieldDelegate
- (BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
...
}
#end
You can use the delegate method of the uitextfield,
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
}
And don't forget to set your textfield.delegate = self in ViewDidLoad.
I want to resign keyboard from UItextview. How to implement UItextView delegate method programmatically.
If u want that ur keyboard is resigned when click on return then u have to write, implement this method....
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if([text isEqualToString:#"\n"]) {
[textView resignFirstResponder];
return NO;
}
return YES;
}
Just make it copy and paste....:)
Make sure you declare support for the UITextViewDelegate protocol.
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if([text isEqualToString:#"\n"]) {
[textView resignFirstResponder];
return NO;
}
return YES;
}
You should use the UITextViewDelegate. You have to declare the use of the protocol in your class header like:
#interface YourClass:NSObject<UITextViewDelegate>
Then in your .m, you should set your class as delegate in some point with something like:
textView.delegate = self;
Then, in your .m again, you have to implement the delegate methods, in particular:
textViewDidChange:
You can read the protocol reference at http://developer.apple.com/library/ios/#documentation/uikit/reference/UITextViewDelegate_Protocol/Reference/UITextViewDelegate.html for more information.
There is no specific delegate method for UITextview to know when user hits "RETURN"
So you can do like this
//In .h File
#interface BlahBlah : UIViewController <UITextViewDelegate>
#property(nonatomic, retain) IBOutlet UITextView *myTextView;
#end
//In .m File
#implementation BlahBlah
#synthesis myTextView;
//In some method, can be viewDidLoad OR viewDidAppear . your convenience ;)
{
self.myTextView.delegate = self;
}
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if([text isEqualToString:#"\n"]) {
[textView resignFirstResponder];
return NO;
}
return YES;
}
Is possible to know when the user touch the keyboard iphone? When the user touch some button from keyboard... :/
The easiest way is to use a TextField. Even is your UI Does not call for one, you can set it's frame to zero so it doesnt show up onscreen. Then you can get access to the keys pressed by using the text field's delegate callback methods.
- (void)viewDidLoad {
[super viewDidLoad];
//CGRectZero because we don't want the textfield to be shown onscreen
UITextField *f = [[UITextField alloc] initWithFrame:CGRectZero];
//We set the delegate so we can grab keypressed
f.delegate = self;
[self.view addSubview:f];
[f becomeFirstResponder]; //Show the keyboard
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string {
if (string.length >0) {
NSLog(#"%# Pressed",string);
}
else {
NSLog(#"Backspcae pressed");
}
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
NSLog(#"return pressed");
return YES;
}
Note: to avoid a compiler warning, make sure in your .h file the class explicitly says it implements the UITextFieldDelegate protocal. ie:
#interface MyViewController : UIViewController <UITextFieldDelegate>