I have a UItextView created with the codes to which I have assigned some gestures. The UItextView should not be editable and I also wanted to remove the possibility to select the text by press and holding on it, including the menu cut/paste which shows up. all over internet I found:
- (BOOL)canBecomeFirstResponder {
return NO;
}
I inserted this code in my file, and set the text.delegate = self. I even included UItextViewDelegate in the .h file
What should I do?
You should modify the editable property of the UITextView.
To disabled copy paste, the easiest way would be to subclass the UITextView, and implement canPerformAction:withSender: like so:
#interface MyTextView : UITextView #end
#implementation MyTextView
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
return NO;
}
#end
If you are using a XIB or Storyboard to layout your UI, make sure to give the text view the correct class.
Related
The question: How do I prevent the copy/paste/select popup that occurs over a UITextView from appearing (not using UIwebView and css)?
I did not want to go the rout of UIWebView as some posts have gone because I already am using UIViews with UITextFields for data entry. I had tried unsuccessfully to implement the solutions dealing with UITextField in my implementation file of my view controller with the methods: targetForAction:withSender, setMenuVisible:animated and finally canPerformAction:withSender. (It NO WORKY WORKY - [sad face])
Ok, I found a working solution (in Xcode 5.1) to my question which, in short, is subclassing the UITextField.
I realized I wasn't really overriding the default behavior of the UITextField in the view controller like I wanted to and neither was putting the methods listed here override the behavior of the textfield delegate in the view controller file. The Key was to subclass the UITextField itself with -targetForAction:withSender. (I know some of you are screaming at the screen about how OBVIOUS that was!) It was not obvious to me. Like most problems when first figuring them out I went through a lot of different paths some I found here in SO. But the solution is a simple one. I want to share this solution in its own area so hopefully it can help someone out.
The header file:
//
//
#import <UIKit/UIKit.h>
#interface TPTextField : UITextField
- (id)targetForAction:(SEL)action withSender:(id)sender;
#end
and the implementation file (.m)
//
//
#import "TPTextField.h"
#implementation TPTextField
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
#pragma mark - method overrides - deny user copy/paste on UITTextFields
- (id)targetForAction:(SEL)action withSender:(id)sender
{
UIMenuController *menuController = [UIMenuController sharedMenuController];
if (action == #selector(selectAll:) || action == #selector(paste:) ||action == #selector(copy:) || action == #selector(cut:)) {
if (menuController) {
[UIMenuController sharedMenuController].menuVisible = NO;
}
return nil;
}
return [super targetForAction:action withSender:sender];
}
#end
In your storyboard or nib/xib file just connect this class to your UITextfield like the picture below:
I have it on git to for easy access here. Please let me know if this is helpful to you!
Tony
If the UITextView is created as an object on a storyboard, the solution is even easier. In Attributes Inspector for the UITextView object, under Behavior, uncheck Editable and uncheck Selectable. Under the Scroll View section, you can check Scrolling Enabled if you want the user to be able to scroll text.
How would I be able to make the keyboard appear automatically when the viewDidLoad? I also do not want to use the UITextField to make the keyboard appear.
Add a UITextField to your view and call it [myTextfield becomeFirstResponder]; Then set it to hidden myTextfield.hidden = true - so the user will never see the textfield.
You can do it by:
subclassing UIView (which is a subclass of UIResponder)
make your UIView Subclas conform to protocol UIKeyInput. To do this add
< UIKeyInput >
in the class declaration and this code to .m file
Add this code:
-(BOOL)hasText;
{
return YES;
}
-(void)insertText:(NSString *)text;
{
// what to do when a text is inserted
}
-(void)deleteBackward;
{
// what to do when delete is pressed
}
-(BOOL)canBecomeFirstResponder
{
// return yes if your control can become first responder and show the keyboard
return YES;
}
create a new instance of this custom view and add it as a subview of the current window (otherwise it won't work)
then, to show the keyboard, you have to simply call [myView becomeFirstResponder];
Just tried and it works well.
Edit: haven't tried, but it should work subclassing not only uiview, but all kind of objects that are subclasses of UIView and that can be added in the window hierarchy, simply it must conform UIKeyInput protocol
The only way I know without an UITextField is creating and adding an instance of the (private, undocumented) UIKeyBoard class. You can find an implementation here, in the showKeyboard:animated: method.
The keyboard that comes up with MFMailComposeViewController does not have any means to dismiss the keyboard once it comes up.
Does anyone have an idea of changing the keyboard. There are no UITextField exposed as you are actually in mail client at the time.
The mail composer isn't yours to modify, it is a system provided view controller which you are explicitly told not to modify in the docs:
Important: The mail composition interface itself is not customizable and must not be modified by your application. In addition, after presenting the interface, your application is not allowed to make further changes to the email content. The user may still edit the content using the interface, but programmatic changes are ignored. Thus, you must set the values of content fields before presenting the interface.
The cancel button is already there in the top left, what would "Done" do? Send the email? That's in the top right.
The MFMailComposeViewController doesn't have a "Done" button, because it assumes you will use that button as a return key (to make a new line).
If you really wanted to change the button to a "done" button, there is only one way I can think to do it:
Create a new MFMailComposeViewController.
Enumerate through [[mailComposer view] subviews].
Inspect each subview (and subviews of subviews, if required).
When you've found the UITextView that is the body, do the following:
// Get the UITextView from subview inspection
UITextView *textView;
// Declare this instance variable in your class #interface
id <UITextViewDelegate> originalTextViewDelegate;
// Get the original delegate
originalTextViewDelegate = [textView delegate];
// Override the delegate
[textView setDelegate:self];
// Set the return key type
[textView setReturnKeyType:UIReturnKeyDone];
Return YES on -textViewShouldEndEditing. Implement ALL UITextViewDelegate methods, and call originalTextViewDelegate (kind of like calling "super" on a subclass).
- (BOOL)textViewShouldEndEditing:(UITextView *)textView
{
[originalTextViewDelegate textViewShouldEndEditing:textView];
// Important: return YES, regardless of originalTextViewDelegate's response
return YES;
}
- (void)textViewDidChangeSelection:(UITextView *)textView
{
[originalTextViewDelegate textViewDidChangeSelection:textView];
}
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
return [originalTextViewDelegate textView:textView shouldChangeTextInRange:range replacementText:text];
}
// etc
That should work, but no guarantees. Hope that helps! :D
We're trying to figure out how to get the keyboard to hide, but we're having problems getting the textFieldShouldReturn to fire. Why?
This is what has been done:
*.h
#interface MultiSalesViewController : UIViewController <UITextFieldDelegate>
*.c
txtCardNumber.delegate = self;
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField setUserInteractionEnabled:YES];
[textField resignFirstResponder];
return YES;
}
Also, the textField has its delegate set to Files Owner in Interface Builder. One odd thing, is that the viewController's - (void)textFieldDidEndEditing:(UITextField *)textField is working.
How to get the hiding of the keyboard working?
I had the exact same issue and it was because I forgot to set the delegate for the text field in interface builder to 'files owner'.
I had the same problem and, as Warren Crowther suggested, I managed to solve it by holding down CTRL and dragging from the TextBox to the "File's Owner" label.
(Gosh, I miss Visual Studio sometimes...!!)
(Apologies for repeating what's already been said, but I thought a screenshot might be useful !)
I had the delegate set and everything. But I was using a UITextView instead of UITextfield...
Perhaps this will help someone trying to figure why delegate methods are not fired.
I see you put it in your code, but for future visitors, add this to your code:
yourTextField.delegate = self;
I think you are using xib. If so You also need to set delegate over there. Do Right Click on your UITextfiled in xib and you will have delegate option drag it to your file owner.
be sure that your MultiSalesViewController implements the UITextFieldDelegate protocol:
#interface MultiSalesViewController : UIViewController <UITextFieldDelegate>
try adding [self becomeFirstResponder]; after [textField resignFirstResponder];
edit:
just another thought.. does your UITextField have a value set for returnKeyType?
txtCardNumber.returnKeyType = UIReturnKeyDone;
i'm not sure if this has to be set for the function to work
following is answer from Mike Gledhill and Warren Crowther updated with xcode 5 screenshot.
(to set UITextField delegate, press and hold ctrl + drag from the UITextField to the "File's Owner" yellow button, shown in image below. if UITextField delegate not set, textFieldShouldReturn method never gets called).
I had everything wired up just right and - (BOOL)textFieldShouldReturn:(UITextField *)textField was still not being called!
As a work around I configured a method to fire on 'EditingDidEnd':
Go to Connection Inspector and connect delegate to view controller .thats it .
Checklist to get it to work:
Did you set your controller as delegate to UITextField Instance?
Make sure controller is not being deallocated by either assigning to property (Autorelease) or explicit retaining it.
I've just started with xcode and objective-c and did some very basic apps, but what i'm having problem with is very basic this. the keyboard return button not hiding the keyboard.
I've searched the internet for the solution and all they say is to connect delegate to the file's owner and add the function and it should work, i did that and nothing is working.
I have an ok button and it is working and also clicking on any free space on the screen is working, just the return button....
I am using the simulator, not testing on iphone yet. (xcode 3.2.5 64 bit with the 4.2 simulator).
This is the line of code that should connect the delegate to every textFiled.
1. i've tried already to return both YES and NO, didn't work.
2. i've tried both a specific object name for the textField and this general way, didn't work.
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
return NO;
}
In the: basic view controller connection -> connections -> outlets, i have the: delegate -- File's Owner. and in the file's owner in referencing outlets there is: delegate - Round style text.....
EDIT - i forgot to mention before, i've check and the method isn't being called!!!
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
NSLog(#"Working!!!");
[textField resignFirstResponder];
return YES;
}
what should i do to make it happen? that is why people say to connect the delegate, but in my case it is connected and not triggering the function...i know it is kind of dumb question but for a nobie like me the solution is not obvious...
OK, another Edit - with all my code: just can't understand what to do....
This is: basicViewController.h:
#import <UIKit/UIKit.h>
#interface basicViewController : <#superclass#> <UITextFieldDelegate>
#interface basicViewController : UIViewController <UITextFieldDelegate> {
//every object that we want to interact with (like text field or lable) is call an outlet!!!!
//here we define the outlets for our program
IBOutlet UITextField *txtName;
IBOutlet UILabel *lblMessage;
}
//here are the getters and setter for our outlets
#property (nonatomic, retain) IBOutlet UITextField *txtName;
#property (nonatomic, retain) IBOutlet UILabel *lblMessage;
//method decleration for the OK button action
- (IBAction) doSomething;
//method for hiding the keyboard when clicking on empty area in the app
//we will put an invisible button on all area and clicking on it will make keyboard disapear
- (IBAction) makeKeyboardGoAway;
#end
This is basicViewController.m:
#import "basicViewController.h"
#implementation basicViewController
//synthesizeing the objects that we made' this will create the getter and setters automaticly
#synthesize txtName;
#synthesize lblMessage;
- (IBAction) doSomething{
// makeing keyboard disapear when pressing ok button (doing that form the text field)
//when pressing the OK button, the keyboard will disapear and when clicking in the text field it will show again
[txtName resignFirstResponder];
NSString *msg = [[NSString alloc] initWithFormat:#"Hello, %#",txtName.text];
//the objective-c way for setting the test in the text field
[lblMessage setText:msg];
//the regular object oriented way
//lblMessage.text = msg;
[msg release];
}
- (IBAction) makeKeyboardGoAway{
[txtName resignFirstResponder];
}
//when clicking the return button in the keybaord
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
NSLog(#"Working!!!");
[textField resignFirstResponder];
return YES;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
#end
Maybe now i am more clear, sorry i didn't do it before.
Any one has an idea what am i doing wrong? it should be pretty strait forward.....
EDIT - Adding an image of all the elements, i hope that will help to help me :-)
10x a lot for every one that is trying to help....i really like this framework, it is so great after c++ and java, python and many other...and i am working with a book, but it is for ios 3.1, maybe that is the problem.....
Firstly you should check if textFieldShouldReturn: is actually being called by adding an NSLog statement or breakpoint at the beginning of the method.
Once that's out of the way, try an manually declare that your view controller conforms to <UITextFieldDelegate> protocol in your interface file:
#interface YourClass : ... <UITextFieldDelegate>
Also declare a property & outlet for your UITextField, make the appropriate connections in IB and manually declare self as the UITextField delegate with:
self.yourUITextFieldObject.delegate = self;
Once that's done see if your method above is now being called and make sure you return YES.
Just write one line in the
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
}
before return YES;
the final version will be as given below:
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
return YES;
}
-(void)textFieldDidEndEditing:(UITextField *)textField{
NSLog(#"%#",textField.text);
}
You need to assign the delegate of the textfields to your file owner. The textfields are sending the message, but doesn't have a delegate to respond to it.
Use the interface builder to do that.
You have to implement this method..
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
Like Rog said, don't forget to register the textfield to the delegate, you can do this manually as he said but in Storyboard you can just control drag from all of your textfields to the view controller and register the delegate (choose delegate). Only the textfields that are registered can make use of all those methods.
So this line is important:
self.yourUITextFieldObject.delegate = self;
Or even more easy these days is to just use the storyboard:
textfield is in a subview? in this case, make sure textfield have as delegate the FileOwner.
put a log at the
- (IBAction) makeKeyboardGoAway
function. I think its this method everytime anything is tapped on the screen. In that case, you will need to send the touch event to the text field. Not sure how this is done but that should do it.
Else try removing the which takes care of tap(click) all over the view and try to do what you are doing.
Most likely the problem is that your actual view controller in the running application is not a "basicViewController" but a UIViewController that does not implement the UITextFieldDelegate-protocol.
What you've done in the interface builder by selecting your class "basicViewController" as the FilesOwner is just declaring the FilesOwner-object in your running application to be of type basicViewController; the actual object is not instantiated by this declaration and in your case it is not in the xib / nib.
Some other part of your code actually instantiates a view controller object and loads the xib / nib file. At that place, I guess your code is instantiating a UIViewController (typically by auto-generated code) and not an instance of your basicViewController; you simply have to change the class there.
Furthermore, this error often happens when using a UINavigationController or UITabBarController in the Interface Builder that is (should be) configured to instantiate and load other custom views. If you use such a higher-level controller, double-check that it is actually configured to use your basicViewController, not UIViewController when loading your view from the xib / nib.
Hope, that solves the issue!
Can you try this..
#interface ClassName : SuperClass < UITextFieldDelegate >
Use like this...
textfield.delegate=self;
and use the UITextFieldDelegate in .h class
You can always dismiss the keyboard when you don’t even know which view the text field is in by using:
Objective-C:
[[UIApplication sharedApplication] sendAction:#selector(resignFirstResponder)
to:nil
from:nil
forEvent:nil];
Swift:
UIApplication.sharedApplication().sendAction("resignFirstResponder",
to:nil,
from:nil,
forEvent:nil)