I want to disable the 'Paste' option for a UITextField and in my UITextField's delegate class, I am providing an implementation for:
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
NSObject(UIResponderStandardEditActions) defines the following actions and I get all of them sent to me in canPerformAction except paste:
#interface NSObject(UIResponderStandardEditActions) // these methods are not implemented in NSObject
- (void)cut:(id)sender __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);
- (void)copy:(id)sender __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);
- (void)paste:(id)sender __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);
- (void)select:(id)sender __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);
- (void)selectAll:(id)sender __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);
- (void)delete:(id)sender __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_2);
- (void)makeTextWritingDirectionLeftToRight:(id)sender __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_5_0);
- (void)makeTextWritingDirectionRightToLeft:(id)sender __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_5_0);
#end
Right now, anytime the clipboard has content in it and I give focus to a UITextField, I see the 'paste' menu displayed.
Is there something else I should be doing to receive the paste message?
create a subclass of UITextField and override the canPerform there, the paste: action is called on the UITextField, and not on the delegate
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 need a way of determining the UITextField that is currently selected in a view. Is this possible without passing a reference or tag?
To be more specific I need to be able to tell which UITextField is selected so that I can hide the keyboard. The reason I need this is because I want to create a UIToolbar to add to all the UITextField's as an input accessory. On this UIToolbar I will add a 'Done' button, when pressed this should hide the keyboard for the currently selected UITextField.
I assume you mean you want to know which UITextField is the first responder (which is the text field that gets input from the keyboard).
There is no public API for this (though there is a private API). You can track which text field is the first responder manually using the textFieldDidBeginEditing: method of each text field's delegate, or you can use a little trickery to find the first responder at any time.
Here's the trick. The UIApplication object knows which object is the first responder, and can send a message to it. So you write a category like this on UIResponder:
UIResponder+firstResponderHack.h
#import <UIKit/UIKit.h>
#interface UIResponder (firstResponderHack)
+ (UIResponder *)firstResponderByHack;
#end
UIResponder+firstResponderHack.m
#import "UIResponder+firstResponderHack.h"
#interface FirstResponderFinder : NSObject
#property (strong, nonatomic) UIResponder *firstResponder;
#end
#implementation FirstResponderFinder
#synthesize firstResponder = _firstResponder;
#end
#implementation UIResponder (firstResponderHack)
- (void)putFirstResponderIntoFinder:(FirstResponderFinder *)finder {
if (self.isFirstResponder)
finder.firstResponder = self;
}
+ (UIResponder *)firstResponderByHack {
FirstResponderFinder *finder = [FirstResponderFinder new];
// Sending an action to nil sends it to the first responder.
[[UIApplication sharedApplication] sendAction:#selector(putFirstResponderIntoFinder:) to:nil from:finder forEvent:nil];
return finder.firstResponder;
}
#end
Then you can find the first responder, and check whether it's a UITextField, like this:
UIResponder *firstResponder = [UIResponder firstResponderByHack];
if (firstResponder && [firstResponder isKindOfClass:[UITextField class]]) {
UITextField *textField = (UITextField *)firstResponder;
// do something with textField
}
There is an easy way to dismiss the keyboard without having to track the currently active control, or iterating through all the available controls, or using a UITextFieldDelegate.
[self.view endEditing:YES]
From the docs:
endEditing:
Causes the view (or one of its embedded text fields) to
resign the first responder status.
- (BOOL)endEditing:(BOOL)force
Parameters
force
Specify YES to force the first responder to resign, regardless of whether it wants to do
so.
Return Value
YES if the view resigned the first responder status or NO if it did not.
Discussion
This method looks at the current view and its subview
hierarchy for the text field that is currently the first responder. If
it finds one, it asks that text field to resign as first responder. If
the force parameter is set to YES, the text field is never even asked;
it is forced to resign.
There is a delegate method:
- (void)textFieldDidBeginEditing:(UITextField *)textField
Apple Docs:
This method notifies the delegate that the specified text field just
became the first responder. You can use this method to update your
delegate’s state information. For example, you might use this method
to show overlay views that should be visible while editing.
There is also a property:
#property(nonatomic, readonly, getter=isEditing) BOOL editing
Apple Docs:
A Boolean value indicating whether the text field is currently in edit
mode. (read-only)
Just make an ivar for the UITextView in your header file:
UITextField *editingField;
#property (nonatomic, copy) UITextField *editingField;
Then,
- (void)textFieldDidBeginEditing:(UITextField *)textField;
{
editingField = textField;
// Whatever else you want to do
}
I'm thinking that you need to diff the textFields without reference.
So, the recommended why is using ObjectiveC runtime.
It's pretty straight forward.
Firstly:
#import <objc/runtime.h>
Then, define a char for its address:
static char UITextFieldViewIdentifier;
Then set the identifier with something like this:
objc_setValue(textField, &UITextFieldViewIdentifier, #"Identifier") //typing on a phone, not so sure about the expression
In the delegate method:
NSString *identifier = objc_getObject(textField, &UITextFieldViewIdentifier)
Just call this line where you want to dismiss the keyboard:
[self.view endEditing:YES];
I work on a project for iPhone iOS 4 with Xcode 4.
I have subclassed a UIButton so that it intercepts single and double tap.
This is the final part of #implementation of the UIButton subclass, two instance methods where the taps are "recorded";
- (void) handleTap: (UITapGestureRecognizer *) sender {
NSLog(#"single tap");
}
- (void) handleDoubleTap :(UITapGestureRecognizer *) sender {
NSLog(#"double tap");
}
A button instance is created in nib and all works OK: it intercepts single tap and double tap and output the NSLog.
Now the question: I have in my ViewController two methods (resetAllFields and populateAllFields) and I need that single tap execute resetAllFields and double tap execute populateAllFields.
How can I do? Where do I put the call?
Thank you.
If you want to handle the behavior in the ViewController the typical solution is to add a #protocol in your custom button class that defines methods for handling the single and double taps.
i.e. in your CustomButton.h
#protocol CustomButtonDelegate <NSObject>
- (void)button:(CustomButton *)button tappedWithCount:(int)count;
#end
You then have a delegate that implements this protocol in your custom button class and call those methods on the delegate when your taps are detected.
i.e. in your CustomButton.h
id <CustomButtonDelegate> _delegate;
in your methods in the implementation:
- (void) handleTap: (UITapGestureRecognizer *) sender {
NSLog(#"single tap");
[self.delegate button:self tappedWithCount:1];
}
- (void) handleDoubleTap :(UITapGestureRecognizer *) sender {
NSLog(#"double tap");
[self.delegate button:self tappedWithCount:2];
}
Your View Controller than implements the protocol methods and sets itself as the custom button's delegate.
ie. in your ViewControllers implementation
- (void)button:(CustomButton *)button tappedWithCount:(int)count {
if (count == 1) {
[self resetAllFields];
} else if (count == 2) {
[self populateAllFields];
}
}
Since you are using Interface Builder to set the custom button you can assign your view controller as a delegate in there or in the ViewDidLoad.
Just ran into UX problem to save UITextField input value.I've got 6 UItextfield entries which saves individual value in sqlite db.
Right now each field has separate save button.So six ones quite look messy and silly.
I just want to know if there is any method to save entry after editing ends.
To be more concise...
I want to save data in UITextField after user ends editing.Just needs 'Saving Logic' for problem
You probably want to use an object which implements UITextFieldDelegate protocol. It defines –textFieldShouldEndEditing: and –textFieldDidEndEditing: methods which are called just before and once text editing ends.
Your delegate should be declared like:
#interface ATextFieldDelegate : NSObject<UITextFieldDelegate>
{
}
#end
And implements the methods:
#implementation ATextFieldDelegate
- (BOOL) textFieldShouldBeginEditing:(UITextField *)textField
{
// Test if the textField.text is valid for storage
// Return YES if it is, NO if not
}
- (void) textFieldDidEndEditing:(UITextField *)textField
{
// Store textField.text into your SQLite database
}
#end
And you should set your UITextField's delegate:
UITextField *myTextField; // could be an IBOutlet
ATextFieldDelegate *myTextFieldDelegate; // must be initialized somewhere
myTextField.delegate = myTextFieldDelegate;
I am trying to make my editable UITextView resign the keyboard (resignFirstResponder) when the user taps "Done." Using a UITextField, I have been able to do this with the following code:
- (IBAction)doneEditing:(id)sender {
[sender resignFirstResponder];
}
... and then to attach it to the relevant UITextField in Interface Builder to the action "Did End on Exit."
However, with a UITextView, I can't seem to access the "Did End on Exit" action. Any suggestions on how to make this happen?
The accepted answer didn't work for me. Instead, the following delegate method should be invoked like this:
- (BOOL) textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if([text isEqualToString:#"\n"]){
[textView resignFirstResponder];
return NO;
}else{
return YES;
}
}
Paste that into the class that you assign to be the UITextView delegate and it'll work.
new Answer
On your View, you'd have a UIBarButton ("Done") that is connected to the IBAction below:
- (IBAction)doneEditing:(id)sender {
[textView resignFirstResponder];
}
Where textView is your textView outlet defined in your .h file and connected in Storyboard or .xib file. Like this:
#property (retain, nonatomic) IBOutlet UITextView *textView;
old Answer
Check the following:
Is UITextViewDelegate specified
in .h
Implement delegate method
for uitextview:
textViewShouldEndEditing, return YES
make sure your .m (controller) is the
delegate for uitextview in IB
resignFirstResponder should now
work.
You can implement UITextViewDelegate and wait for "\n", in Swift 4 :
myTextView.delegate = self
// ...
extension MyViewController : UITextViewDelegate {
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if text == "\n" {
textView.resignFirstResponder()
return false
}
return true
}
}
To have the done button dismiss the keyboard and resignFirstResponder you have to implement a delegate method.
In your .h implement the UITextFieldDelegate
#interface YourViewController : UIViewController <UITextFieldDelegate>
Then implement the textFieldShouldReturn in your .m
-(BOOL) textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
Don't forget to link the delegate of UITextField to the file's Owner (very important)