How to toggle autocorrectionType on and off for an existing UITextView - objective-c

I have a UITextView in my iPhone app for which I want to be able to toggle the autocorrectionType.
When a user is editing the text view, I want the autocorrectionType to be set to UIAutocorrectionTypeYes.
When the text view is not being edited, I want the autocorrectionType to be set to UIAutocorrectionTypeNo (because I don't want any of the red-dotted underlines generated by autocorrection to be visible)
Simply toggling the autocorrectionType like this:
myTextView.autocorrectionType = UITextAutocorrectionTypeYes;
myTextView.autocorrectionType = UITextAutocorrectionTypeNo;
Doesn't seem to work.
Are there limitations on when I can toggle the autocorrectionType or in which situations the changed autocorrectionType takes effect?
EDIT:
To clarify:
There are no issues setting the autocorrectionType when initializing the UITextView. The problem arises when I want to change the autocorrectionType for an existing UITextView. In my case I want to give users the advantage of autocorrection when they edit a UITextView, but don't want any spelling errors pointed out with the red-dotted underlines when the UITextView is not being edited - in part because I am also exporting a UIView containing the UITextView as an image.
The problem is that just changing the value of my UITextView's autocorrectionType property doesn't work.

Here's an easy way to do this for the image export scenario :
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
// Turn spell check on
textView.autocorrectionType = UITextAutocorrectionTypeYes;
return YES;
}
- (BOOL)textViewShouldEndEditing:(UITextView *)textView
{
// Turn spell check off and clean up red squiggles.
textView.autocorrectionType = UITextAutocorrectionTypeNo;
NSString *currentText = textView.text;
textView.text = #"";
textView.text = currentText;
return YES;
}

You can try to first hide the keyboard first and then displaying it again. Also update the uitextview. If [UITextView setNeedsDisplay] doesn't work for you, try [UITextView insertText:] and then [UITextView deleteBackward]
[textView resignFirstResponde];
textView.autocorrectionType = UITextAutocorrectionTypeNo;
[textView becomeFirstResponder];
[textView setNeedsDisplay];
or
[textView insertText:#" "];
[textView deleteBackward];

In addition to changing the autocorrection type to UITextAutoCorrectionNo, the UITextView must be forced to reevaluate its correction state. setNeedsRedraw is insufficient but setting the text to itself, e.g.
textView.autocorrectionType = UITextAutocorrectionTypeNo;
textView.text = textView.text;
makes the red dashed lines go away. NOTE: this workaround relies on undocumented behavior and is not guaranteed to work on future iOS releases.

Try calling -setNeedsDisplay on the text view after you've changed the autocorrectionType. This will force the text view to redraw and will hopefully clear the red underlines.
myTextView.autocorrectionType = UITextAutocorrectionTypeNo;
[myTextView setNeedsDisplay];

func activateTextViewAutocorrection() {
textView.autocorrectionType = .default
textView.reloadInputViews()
}
func deactivateTextViewAutocorrection() {
textView.autocorrectionType = .no
textView.reloadInputViews()
}

Related

Editable transparent NSTextField text appears with white highlight

I am trying to create editable transparent NSTextField in a semi transparent window:
What I have noticed is that whenever the field is editable there is a white "selection like" background drawn even though the element is not actually selected.
Additional observable symptoms:
This highlight is not present when the field is set as non-editable.
If there are multiple fields only the first one has the highlight.
The highlight is not present if the text is not set programmatically
Following code was used to generate the field:
f = [[NSTextField alloc] initWithFrame:b2];
f.backgroundColor = [NSColor clearColor];
f.drawsBackground = YES;
f.bordered = NO;
f.bezeled = NO;
f.focusRingType = NSFocusRingTypeNone;
f.textColor = [NSColor whiteColor];
f.editable = YES;
f.selectable = YES;
f.backgroundColor = [NSColor clearColor];
f.allowsEditingTextAttributes = YES;
f.stringValue = #"Foo";
[self.contentView addSubview:f];
Additional observations (potentially a separate problem):
When field is not the first field on the screen and the initial text is set programmatically and removed by editing the field there is a shadow of the text:
I can't seem to find any documentation on this I wonder if any of you have had this happen and potentially have a solution or a pointer to docs I might have not stumbled upon.
part 1: removing highlight
there are two options here depending on the behavior you are looking for
option 1 - nil first responder
TextField is not first responder
No highlighted text
No Cursor at the end of text
Assuming you are using an NSWindow, set the first responder to nil after calling makeKeyAndOrderFront
[self.window makeKeyAndOrderFront:self];
[self.window makeFirstResponder:nil];
It appears as though makeKeyAndOrderToFront: looks for the first NSResponder in the window willing to accept first responder. Then becomeFirstResponder is called on that responder; leading to option 2
option 2 - override becomeFirstResponder
TextField is first responder
No highlighted text
Cursor appears at the trailing edge of text
Subclass NSTextfield and override it's becomeFirstResponder method
#implementation BPTextField
- (BOOL)becomeFirstResponder {
BOOL isResponder = [super becomeFirstResponder];
//Get Field editor, set selected range
NSText* fieldEditor = [[self window] fieldEditor:YES forObject:self];
[fieldEditor setSelectedRange:NSMakeRange(fieldEditor.string.length ,0)];
return isResponder;
}
#end
I prefer this option from a usability perspective
part 2: removing shadow
option 1 - add a solid background color
I'm not clear ; ) on why this is the case, but if you add a solid background color, the text will update.
option 2 - override textDidChange
override textDidChange:notification in your textfield
#implementation BPTextField
- (void)textDidChange:(NSNotification *)notification {
[super textDidChange:notification];
[self setNeedsDisplay:YES];
}
#end
Final notes
You'll notice that the text looks bad, or rigid. Adding a background color to the textfield, or to the superview's layer will fix this.
This is an answer to part 2 of the question.
The shadow artifact is from rendering window's shadow which is not updated when the text in the NSTextField changes.
If the window's hasShadow method returns "NO" the text's shadow will not create shadow for the text either.

UITextField IOS7 not setting font color during input

I have some simple code that worked fine under iOS6. In a UITextField when the event editingDidBegin arrived I executed a simple piece of code that changed the color of the text that was entered:
textField.textColor = [UIColor redColor];
Although this code is executed, the text color does not change to red, but remains unchanged at its default color as the text is being entered.
If I call this method on editingDidEnd, the text is entered in the default color, but changes to red when editingDidEnd kicks off the same piece of code:
textField.textColor = [UIColor redColor];
It seems as though I can not change the textColor property when the textField is the first responder.
Any help here would be greatly appreciated.
You should do some subclassing for that
Here is a good solution that works both on ios6 and ios7
http://www.brightec.co.uk/blog/how-change-colour-uitextfields-placeholder-text-ios7-and-still-support-ios6
I found another way of accomplishing this. I used the UITextField delegate method and added the following code. Seems like my original method should have worked moving to IOS7, but this now works fine.
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
textField.textColor = [UIColor redColor];
return YES;
}
[textField setValue:[UIColor redColor] forKeyPath:#"_placeholderLabel.textColor"];
This will change the place holder color of UITextField,

Setting UITextView frame to content size no longer works in Xcode 5

The code snippet below worked to resize a UITextView frame to it's content height, before installing Xcode 5 but it doesn't work since the upgrade:
CGRect frame = _textView.frame;
frame.size.height = _textView.contentSize.height;
_textView.frame = frame;
I've searched and haven't found the fix. Any thoughts?
There's new stuff for this on iOS 7.
To get the "fitted" size used by the text view after it's updated its text, call usedRectForTextContainer: on the textView's layoutManager property, passing the textView's textContainer property as an argument.
Word of warning about scrolling: Be advised, though, that changing the frame size of a text view after it has updated it's text can have unexpected visual bugs if scrolling is disabled on your text view. If this happens, set scrolling enabled before editing the text of the text view, then disabling it after it's updated (if you need scrolling to remain disabled).
To work in iOS 7 (Xcode 5), just:
Give the entire space to receive the text, by setting:
[myTextView setScrollEnabled:YES];
Pass the real text:
myTextView.text = theTextVariable; or myTextView.text = #"The text...";
Autoresize textView:
[myTextView sizeToFit];
Disable scroll:
[myTextView setScrollEnabled:NO];
P.S: myTextView can be use also as self.myTextView or _myTextView
And have fun!
I believe the correct way to force a textView to update its contentSize is by calling
[textView layoutIfNeeded]
However, in iOS 7.0 and 7.1 this seems still not to work reliably unless you first set
textView.layoutManager.allowsNonContiguousLayout = false;
It's not clear to me whether this is a bug or not since I can't really find a good explanation of what "non-contiguous layout" even means.
(My personal use case is updating textView.text = newValue programmatically, then trying to resize the textView appropriately.)
[textView sizeToFit];
Is what you need.
All you need to do is make sure that:
[textView setScrollEnabled:YES];
BEFORE you set the UITextView text content.
You can then:
[textView sizeToFit];
[textView setScrollEnabled:NO];
After you've set the text. Same as writing your own bling function or employing complicated bounding rect methods. Why use something so complicated when the solution is as simple as three lines?
That said, wrap those functions like so:
- (void) setText:(NSString *)theTextToAdd andResizeTheDamnTextView:(UITextView *)textView {
[textView setScrollEnabled:YES];
[textView setText:theTextToAdd];
[textView sizeToFit];
[textView setScrollEnabled:NO];
}
And define it in a per-file or global basis to avoid having to manually write or copy/paste the four lines and call it every time. Just call it as:
[yourTextViewIvar setText:#"DUMMY STRING" andResizeTheDamnTextView:yourTextViewIvar];
If that doesn't work:
[yourTextViewIvar setText:[self setText:#"DUMMY STRING" andResizeTheDamnTextView:yourTextViewIvar]];
And you'll be golden.
I think..
That's Pseudocode. Just FYI.
A easier solution is use that:
[textViewExample sizeToFit];
This work for me.

UITextField -- Adding UIView for leftView - Can't get Focus

The UITextFields in my app have placeholder text defined (in Interface Builder), and I cannot cause these fields to acquire focus (i.e. show the keyboard and allow editing) when I tap on the area occupied by the placeholder text. If I tap on the textfields in an area just outside the that of placeholder text (though still within the bounds of the textfiled itself), it acts as normal (i.e. the keyboard pops up and I can edit the content of the textfield). How can I fix this?
Thanks.
EDIT 1
Ok, I think I've got it. I'm also setting a blank view to the "leftView" property of these UITextFields. If I remove this, you can touch the UITextFields in the area of the placeholder text and it reacts as expected; I need this view for the leftView though. If you change the background color of this spacer view to red, you can see that it doesn't get in the way at all, so I don't know what's going wrong.
Why does this code cause this problem?
Thanks.
+(UIView*)getTextFieldLeftSpacerViewWithBackgroundColor:(UIColor*)backgroundColor andHeight:(CGFloat)height
{
UIView *leftWrapper = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 8.0f, height)];
leftWrapper.autoresizingMask = UIViewAutoresizingNone;
[leftWrapper setOpaque:YES];
if(backgroundColor){leftWrapper.backgroundColor = backgroundColor;}
else{leftWrapper.backgroundColor = [UIColor clearColor];}
return [leftWrapper autorelease];
}
+(void)setTextFieldLeftSpacerForTextFieled:(UITextField*)textField
{
if(textField)
{
UIView *spacer = [MYViewController getTextFieldLeftSpacerViewWithBackgroundColor:nil andHeight:textField.bounds.size.height];
textField.leftView = spacer;
textField.leftViewMode = UITextFieldViewModeAlways;
}
}
Just ran into the same problem and didn't want to subclass, just had to use :
leftWrapper.userInteractionEnabled = NO;
I abandoned this approach. Instead of using an invisible view to offset the text, I opted to subclass UITextField and provide offset CGRects for the bounds of the text within theUITextField. The following SO post was very helpful:
Indent the text in a UITextField

Change font color of UITextView

I have a UITextView where the user can input text. Say the user has already inputted a value. How can I change the font color of that already typed text and future typed text to a different one with the click of a button?
I already have it set up where I can change the color of the text but it only works if I choose a color BEFORE I start typing. After I start typing and I attempt to change the color, it doesn't do anything.
I have this:
-(IBAction)changeInkColor:(id)sender
{
[inkTextField setTextColor:[UIColor greenColor]];
inkTextField.text=#"text";
}
and that actually works and displays "text" in green only if there is no text already in the view. However if I type something in and then hit this button, nothing happens.
I just tried that and I had no problems. I set up a button that called [myTextView setTextColor:[UIColor redColor]];
After typing a bit with black text color, I pressed the button, and everything turned red. Then I continued typing, all in red.
Are you using setTextColor: to do this also?
In the end, setTextColor: is the answer, there's an important detail missing from the earlier answers: To get this to work in iOS 8, I had to set the color =after= I set the text.
Hence,
- (void)viewDidLoad
{
[super viewDidLoad];
_myTextView.textColor = [UIColor whiteColor];
_myTextView.text = #"yadda yadda yadda...";
// etc., snip
Did NOT work, while
- (void)viewDidLoad
{
[super viewDidLoad];
_myTextView.text = #"yadda yadda yadda...";
_myTextView.textColor = [UIColor whiteColor];
// etc., snip
DID work. This strikes me as a bug in iOS 8, which I will write up.
You can fix this (at least in Xcode 8.2) in IB by toggling the textColor button (6th button in the row). With this button selected, if you set the textColor programmatically before you enter text in the view, the color will "stick." I have not found an elegant way to set this on the text view programatically.
However you can also work around this in code:
textView.text = #" ";
textView.textColor = UIColor.redColor;
textView.text = #"";
I had the same problem as you, then I realised that the text was not changing colour, and was red by default because I was doing:
placeholder = #"Welcome";
instead of
WelcomeField.text = #"Welcome";
Hope it helps
use attributed text of UITextField
NSAttributedString *string = [[NSAttributedString alloc]initWithString:self.textField.text attributes:#{NSForegroundColorAttributeName:color}];
self.textField.attributedText = string;
Very interestingly, while
[_nameLabel setTextColor: [UIColor redColor]];
didn't work,
_nameLabel.textColor = [UIColor redColor]];
worked. Hope it helps for others. Cheers.