UITextView shouldChangeTextInRange delegate not called - objective-c

I am using this code to set the parameters of an uitextview i have on my view.
_textview=[[UITextView alloc]init];
[_textview setUserInteractionEnabled:FALSE];
_textview.text=#"Write your message";
_textview.textColor=[UIColor lightGrayColor];
_textview.layer.cornerRadius=6;
_textview.contentInset = UIEdgeInsetsZero;
_textview.delegate=self;
I have in the .h this code
IBOutlet UITextView *_textview;
#property(nonatomic,retain) IBOutlet UITextView *_textview;
I have connected the outlet to the uitextview by using the interface.
What happens is the following:
- (void)textViewDidChange:(UITextView *)inTextView
the above delegate is called but not the following one:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementString:(NSString *)string
Why is this happening? Am i doing something wrong?
Any help appreciated...

In addition to removing the _textview = [[UITextView alloc]init]; so as to not overwrite your nib loaded textview.
The <UITextViewDelegate> method is:
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{}
The correct method signature is:
textView:shouldChangeTextInRange:replacementText:
not:
textView:shouldChangeTextInRange:replacementString:

Because you are typing the method name wrong.
There is no
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementString:(NSString *)string
but only
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
careful with the different between replacementString and replacementText.
Also, as the others said, if you've created the UITextView in IB, you should NOT init it again in your code (but this is not the reason why your delegate never invoked).

Related

UITextViewDelegate not called

My UITextView delegate is not getting called. I set the delegate of the textview to self in cell for row by saying cell.textview.delegate=self. (The cell is a custom subclassed cell with UITextView property.) Nevertheless, in my tableViewController the following line does not get called:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
Why?

How to get a dynamically changing NSTableView in OSX

I am new to coding for Mac. I am familiar with UITableView's from iOS coding, but can't seem to get NSTableView to work properly on my app. Yes I have looked through documentation and tutorials, but I am having trouble getting the result I need. My desired outcome should be pretty basic and simple, but I am stumped on the TableViews. I would really like it to function more like how it does with a UITableView rather than how it seems to want to function with NSTableView. I don't want to add or remove rows. I only need 1 column and I would really like for it to work like a list of buttons that can be pressed and trigger the content associated with that option on the same screen on the next NSView over.
(I have 3 views on one screen. The first is the main menu to the left and when pressed triggers the tableView to display the submenu. When that option is selected it opens the content on the far right of the screen. My desired result anyways.)
Currently nothing is populating the tableview. This is what it currently looks like.
.h
#interface RootViewController : NSViewController <NSTableViewDataSource>{
IBOutlet NSView *mainMenuView;
IBOutlet NSTableView *tableView;
NSMutableArray *options;
}
-(IBAction)mainMenuBtn:(id)sender;
#end
.m
#interface RootViewController ()
#end
#implementation RootViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
options = [[NSMutableArray alloc] init];
}
return self;
}
-(void)viewDidLoad{
}
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView{
return [options count];
}
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row{
return [[options objectAtIndex:row] valueForKey:[tableColumn identifier]];
}
-(IBAction)mainMenuBtn:(id)sender{
NSLog(#"1");
[options addObject:#"Strain 1"];
NSString *test = [options objectAtIndex:0];
NSLog(test);
[tableView reloadData];
}
Currently I have tableView connected in the NIB to the TableView. I attempted to connect dataSource to File's Owner, but that didn't work. Can't seem to find any place else to hook it up too. Any suggestions would be greatly appreciated. Thanks
First the dataSource of the NSTableView must be connected to your RootViewController instance in Interface Builder, or through code.
Something that seems a little suspicious to me is the line:
return [[options objectAtIndex:row] valueForKey:[tableColumn identifier]];
I don't know what is the value for the [tableColumn identifier] but it must match the property of the objects you're adding to your array. I can see that the objects you're adding are strings, so [tableColumn identifier] must be a property of class NSString. If you're using a string as the array's object, try using this:
return [options objectAtIndex:row];

Hiding Keyboard on UITextView

I'd like to thanks you in advance for your answers. I read all stuff about this but I couldn't solve it.
I know how to hide keyboard on UITextField, just like this:
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
[placename resignFirstResponder];
[address resignFirstResponder];
return YES;
}
But I also have an UITextView and I don't know how to hide it. I don't want to hide it with a button I want to hide it with a "Done" in the return.
I read something like this:
[textField setReturnKeyType: UIReturnKeyDone];
But... how and where to implement it? I'm new on this so I need to know it step by step,please.
Thanks so much.
(Sorry I'm not able to send an image...new user ;) )
Its easy. Have textview delegate in your controller and add following method.
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if([text isEqualToString:#"\n"]) {
[textView resignFirstResponder];
return NO;
}
return YES;
}
There is one disadvantage using this, user can not write multi line statements. To solve this you can have a create view over keyboard and have button over there and add action to resign your textview.
Credit to this question
Additional to #JanakNirmal Answers, the code for the .h and .m. Works fine for me.
.h
#interface ViewController : UIViewController <UITextViewDelegate>
#property (weak, nonatomic) IBOutlet UITextView *textField; // connected with IB
#end
.m
#interface ViewController ()
- (void)viewDidLoad
{
[super viewDidLoad];
// Done key and hide keyboard
[self.textField setDelegate:self];
[self.textField setReturnKeyType:UIReturnKeyDone];
}
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
if ([text isEqualToString:#"\n"])
{
[textView resignFirstResponder];
}
return YES;
}
#end

iOS Xcode keyboard done button function

I just can't make the "Done" button to quit the keyboard.
I used this in my controller.h file
- (IBAction)textFieldDoneEditing:(id)sender;
and this for my controller.m file
- (IBAction)textFieldDoneEditing:(id)sender {
[sender resignFirstResponer];
}
and I'm mixed up in wiring the .xib part.
Make the controller a delegate of the UITextField/UITextView in IB or from code like textField.delegate = self;
Editted:
For this you need to declare the controller a delegate of UITextFieldDelegate/UITextViewDelegate as
#interface Controller : <UITextFieldDelegate> { ...
, then override the method:
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
return YES;
}
for UITextField and
-(BOOL)textViewShouldEndEditing:(UITextView *)textView{
[textView resignFirstResponder];
return YES;
}
for UITextView
In your .xib, right click on your text view, drag to "File's Owner", and click "delegate". Should work now?
Edit: Whoops, sorry I'm an idiot, do what that other guy says. If you don't know how to set the delegate in code though, you can do it my way in IB.
Let me make my first contribution:
If you have multiple text fields, group them in a #property (strong, nonatomic)
*.h
#property (strong, nonatomic) IBOutletCollection(UITextField) NSArray *collectingData;
*.m
-(BOOL)textFieldShouldReturn:(UITextField *)boxes
{
for (UITextField *boxes in collectingData) {
[boxes resignFirstResponder];
}
return YES;
}

Programmatically dismissing textfield keyboard with delegate

I have a viewController with this:
#interface RootViewController : UIViewController <UITextFieldDelegate>{
Then I have a textfield added programmatically like this in viewController.m:
UITextField*textFieldRounded=[[UITextField alloc] initWithFrame:frame];
textFieldRounded.delegate = self;
In the same .m i have tried all of these:
- (void)textFieldDidEndEditing:(UITextField *)textField{
[textField resignFirstResponder];
NSLog(#"returned?");
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
NSLog(#"returned?");
return YES;
}
-(BOOL)textFieldShouldEndEditing:(UITextField *)textField{
[textField resignFirstResponder];
NSLog(#"returned?");
return YES;
}
The keyboard appears fine when I click the text field, which is in a subview of the viewController. but pressing Done does nothing. The NSLog statements never appear, so these methods are never getting called. Any ideas?
I just barely had this question, maybe, but what I did was attached a tap gesture recognizer object to the view, made a instance method called clear keyboard:, and inside the function I put [whateverItIsThatOpenedTheKeyboard resignFirstResponder]; and that's it. Maybe you asking something totally different, but I thought I would try and help :)
Declare the UITextField in .h file as an IBOutlet with property and synthesize it in .m file.
Use this delegate method
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;
Add this delegate method to your code and run your app once again..