Get Currently Typed Word in UItextview

Get currently typed word in a UITextView

The UITextView delegate method : -textView:textView shouldChangeTextInRange:range replacementText:text what actaully does is that it asks whether the specified text should be replaced in the text view in the specified range of textView.text .

This method will be invoked each time when we type a charactor before updating that to the text view. That is why you are getting the range.location as 0, when you type the very first character in the textView.

Only if the return of this method is true, the textView is getting updated with what we have typed in the textView.

This is the definition of the parameters of the -textView:textView shouldChangeTextInRange:range replacementText:text method as provided by apple:

range :- The current selection range. If the length of the range is 0, range reflects the current insertion point. If the user presses the Delete key, the length of the range is 1 and an empty string object replaces that single character.

text :- The text to insert.

So this is what the explanation for the method and your requirement can meet like as follows:

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
//Un-commend this check below :If you want to detect the word only while new line or white space charactor input
//if ([text isEqualToString:@" "] || [text isEqualToString:@"\n"])
//{
// Getting the textView text upto the current editing location
NSString * stringToRange = [textView.text substringWithRange:NSMakeRange(0,range.location)];

// Appending the currently typed charactor
stringToRange = [stringToRange stringByAppendingString:text];

// Processing the last typed word
NSArray *wordArray = [stringToRange componentsSeparatedByString:@" "];
NSString * wordTyped = [wordArray lastObject];

// wordTyped will give you the last typed object
NSLog(@"\nWordTyped : %@",wordTyped);
//}
return YES;
}

Get the last word that is being typed

Try with below code, its working at my end.

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
let nsString = textView.text as NSString?
let newString = nsString?.replacingCharacters(in: range, with: text)
let arr = newString?.components(separatedBy: " ")
self.lblWord.text = arr?.last
return true
}

UITEXTVIEW: Get the recent word typed in uitextview

//This method looks for the recent string entered by user and then takes appropriate action.

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {

//Look for Space or any specific string such as a space
if ([text isEqualToString:@" "]) {
NSMutableCharacterSet *workingSet = [[NSCharacterSet whitespaceAndNewlineCharacterSet] mutableCopy];

NSRange newRange = [self.myTextView.text rangeOfCharacterFromSet:workingSet
options:NSBackwardsSearch
range:NSMakeRange(0, (currentLocation - 1))];

//The below code could be done in a better way...
UITextPosition *beginning = myTextView.beginningOfDocument;
UITextPosition *start = [myTextView positionFromPosition:beginning offset:currentLocation];
UITextPosition *end = [myTextView positionFromPosition:beginning offset:newRangeLocation+1];
UITextRange *textRange = [myTextView textRangeFromPosition:end toPosition:start];

NSString* str = [self.myTextView textInRange:textRange];
}
}

UITextField get currently edited word

Ok I found a way to do it quite easily. Maybe someone will find it useful:

UITextRange* selectedRange = [textField selectedTextRange];
NSInteger cursorOffset = [textField offsetFromPosition:0 toPosition:selectedRange.start];
NSString* text = textField.text;
NSString* substring = [text substringToIndex:cursorOffset];
NSString* editedWord = [[substring componentsSeparatedByString:@" "] lastObject];

How to detect a string after the '@' is typed in a textview

So you aren't currently getting the whole word in currentWord. It looks like you're only getting the @ character. currentWord is a variable and it doesn't look like you're properly iterating through all of the characters in the textField. This is how I would handle that:

if let splitText = textField.text?.split(separator: " ") {
for word in splitText {
if word.hasPrefix("@") {
print(word) // call whatever function you need here
} else {
print("NOPE")
}
}
} else {
print("No Text!!")
}

This will only fire when it finds an @ and the word contains the @ and every character after the @ until a " " (space)

Get current paragraph in UITextView?

It sounds like you need NSString's paragraphRangeForRange: method:

let composeText = composeTextView.text as NSString
let paragraphRange = composeText.paragraphRangeForRange(composeTextView.selectedRange)
print(composeText.substringWithRange(paragraphRange))

Get tapped word from UITextView in Swift

You need to add the UITapGestureRecognizer to the UITextView that you want to be able to tap. You are presently adding the UITapGestureRecognizer to your ViewController's view. That is why the cast is getting you into trouble. You are trying to cast a UIView to a UITextView.

let tapGesture = UITapGestureRecognizer(target: self, action: #selector(textTapped))
tapGesture.numberOfTapsRequired = 1
myTextView.addGestureRecognizer(tapGesture)

Technically recognizer.view is an optional type (UIView!) and could be nil, but it seems unlikely that your textTapped() would be called it that wasn't set. Likewise, the layoutManager is of type NSLayoutManager!. To be on the safe side though, the Swift way to do this is:

guard let textView = recognizer.view as? UITextView, let layoutManager = textView.layoutManager else {
return
}
// code using textView and layoutManager goes here

In fact, if you had written it this way, you wouldn't have crashed because the conditional cast of the UIView to UITextView would not have succeeded.

To make this all work then, add attributes to your attributed string that you will extract in your textTapped routine:

var beginning = NSMutableAttributedString(string: "To the north you see a ")
var attrs = [NSFontAttributeName: UIFont.systemFontOfSize(19.0), "idnum": "1", "desc": "old building"]
var condemned = NSMutableAttributedString(string: "condemned building", attributes: attrs)
beginning.appendAttributedString(condemned)
attrs = [NSFontAttributeName: UIFont.systemFontOfSize(19.0), "idnum": "2", "desc": "lake"]
var lake = NSMutableAttributedString(string: " on a small lake", attributes: attrs)
beginning.appendAttributedString(lake)
myTextView.attributedText = beginning

Here's the full textTapped:

@objc func textTapped(recognizer: UITapGestureRecognizer) {
guard let textView = recognizer.view as? UITextView, let layoutManager = textView.layoutManager else {
return
}
var location: CGPoint = recognizer.locationInView(textView)
location.x -= textView.textContainerInset.left
location.y -= textView.textContainerInset.top

/*
Here is what the Documentation looks like :

Returns the index of the character falling under the given point,
expressed in the given container's coordinate system.
If no character is under the point, the nearest character is returned,
where nearest is defined according to the requirements of selection by touch or mouse.
This is not simply equivalent to taking the result of the corresponding
glyph index method and converting it to a character index, because in some
cases a single glyph represents more than one selectable character, for example an fi ligature glyph.
In that case, there will be an insertion point within the glyph,
and this method will return one character or the other, depending on whether the specified
point lies to the left or the right of that insertion point.
In general, this method will return only character indexes for which there
is an insertion point (see next method). The partial fraction is a fraction of the distance
from the insertion point logically before the given character to the next one,
which may be either to the right or to the left depending on directionality.
*/
var charIndex = layoutManager.characterIndexForPoint(location, inTextContainer: textView.textContainer, fractionOfDistanceBetweenInsertionPoints: nil)

guard charIndex < textView.textStorage.length else {
return
}

var range = NSRange(location: 0, length: 0)
if let idval = textView.attributedText?.attribute("idnum", atIndex: charIndex, effectiveRange: &range) as? NSString {
print("id value: \(idval)")
print("charIndex: \(charIndex)")
print("range.location = \(range.location)")
print("range.length = \(range.length)")
let tappedPhrase = (textView.attributedText.string as NSString).substringWithRange(range)
print("tapped phrase: \(tappedPhrase)")
var mutableText = textView.attributedText.mutableCopy() as NSMutableAttributedString
mutableText.addAttributes([NSForegroundColorAttributeName: UIColor.redColor()], range: range)
textView.attributedText = mutableText
}
if let desc = textView.attributedText?.attribute("desc", atIndex: charIndex, effectiveRange: &range) as? NSString {
print("desc: \(desc)")
}
}

How can I get the current selected line number inside UITextView?

EDIT: I've obviously ignored the currently selected part of your question.
I'll still keep the code here in case someone needs it.

Have you tried counting the newline separator?

let str = "First\nSecond\nThird"
let tok = str.componentsSeparatedByString("\n")
print(tok.count) // Hopefully prints "3"

Get word from character index in textView (iOS)

The issue apparently seemed to stem from the .x and .y values I set after getting location. All I had to do was remove these lines:

location.x -= textView.textContainerInset.left
location.y -= textView.textContainerInset.top


Related Topics



Leave a reply



Submit