I am working on Text to speech application in iPhone,
我正在研究iPhone的文本到语音应用,
in which have a text field that takes input, i want user to select some portion of text from text field and my application will convert that selected text into speech.
在文本字段接受输入的情况下,我希望用户从文本字段中选择文本的某些部分,我的应用程序将选择的文本转换为语音。
my problem is how would i get the text that user has selected from text field?
我的问题是如何从文本字段中获取用户选择的文本?
5 个解决方案
#1
26
-[UITextField selectedText]
Although UITextField
doesn't have a selectedText
method, it conforms to the UITextInput
protocol. So, you can use the required properties & methods of the UITextInput
protocol to determine the selectedText
of a UITextField *textField
(or any object that conforms to the UITextInput
protocol, such as a UITextView
).
虽然UITextField没有selectedText方法,但它符合UITextInput协议。因此,您可以使用UITextInput协议所需的属性和方法来确定UITextField *textField的selectedText(或任何符合UITextInput协议的对象,如UITextView)。
NSString *selectedText = [textField textInRange:textField.selectedTextRange];
NSLog(@"selectedText: %@", selectedText);
As an aside, you can also use the required properties & methods of the UITextInput
to calculate the selectedRange
of a UITextField *textField
.
顺便说一下,您还可以使用UITextInput所需的属性和方法来计算UITextField *textField的selectedRange。
UITextRange *selectedTextRange = textField.selectedTextRange;
NSUInteger location = [textField offsetFromPosition:textField.beginningOfDocument
toPosition:selectedTextRange.start];
NSUInteger length = [textField offsetFromPosition:selectedTextRange.start
toPosition:selectedTextRange.end];
NSRange selectedRange = NSMakeRange(location, length);
NSLog(@"selectedRange: %@", NSStringFromRange(selectedRange));
-[UITextFieldDelegate textFieldDidChangeSelection:]
Although, UITextFieldDelegate
doesn't declare a textFieldDidChangeSelection:
delegate method like -[UITextViewDelegate textViewDidChangeSelection:]
, you can still hook into when the selection of a UITextField
has changed. To do so, subclass UITextField
and use method swizzling to add your own code to the textField.inputDelegate
's native implementation of -[UITextInputDelegate selectionDidChange:]
.
尽管UITextFieldDelegate没有声明textFieldDidChangeSelection:委托方法,比如-[UITextViewDelegate textViewDidChangeSelection:],但是当UITextField的选择发生变化时,您仍然可以继续使用它。为此,子类UITextField和使用方法swizzle将您自己的代码添加到textField。inputDelegate的本机实现-[UITextInputDelegate selectionDidChange:]。
// MyTextField.h
#import <UIKit/UIKit.h>
@interface MyTextField : UITextField
@end
// MyTextField.m
#import <objc/runtime.h>
#import "MyTextField.h"
UIKIT_STATIC_INLINE void mySelectionDidChange(id self, SEL _cmd, id<UITextInput> textInput);
@implementation MyTextField {
BOOL swizzled;
}
#pragma mark - UIResponder
// Swizzle here because self.inputDelegate is set after becomeFirstResponder gets called.
- (BOOL)becomeFirstResponder {
if ([super becomeFirstResponder]) {
[self swizzleSelectionDidChange:YES];
return YES;
} else {
return NO;
}
}
// Unswizzle here because self.inputDelegate may become the inputDelegate for another UITextField.
- (BOOL)resignFirstResponder {
if ([super resignFirstResponder]) {
[self swizzleSelectionDidChange:NO];
return YES;
} else {
return NO;
}
}
#pragma mark - Swizzle -[UITextInput selectionDidChange:]
// Swizzle selectionDidChange: to "do whatever you want" when the text field's selection has changed.
// Only call this method on the main (UI) thread because it may not be thread safe.
- (void)swizzleSelectionDidChange:(BOOL)swizzle {
if (swizzle == swizzled || ![self respondsToSelector:@selector(inputDelegate)]) return; // 4.3
Class inputDelegateClass = object_getClass(self.inputDelegate);
SEL mySelector = @selector(mySelectionDidChange:);
class_addMethod(inputDelegateClass, mySelector, (IMP)mySelectionDidChange, "v@:@");
Method myMethod = class_getInstanceMethod(inputDelegateClass, mySelector);
Method uiKitMethod = class_getInstanceMethod(inputDelegateClass, @selector(selectionDidChange:));
method_exchangeImplementations(uiKitMethod, myMethod);
swizzled = swizzle;
// NSLog(@"swizzled? %i", method_getImplementation(uiKitMethod) == (IMP)venmo_selectionDidChange);
}
@end
UIKIT_STATIC_INLINE void mySelectionDidChange(id self, SEL _cmd, id<UITextInput> textInput) {
// Call the native implementation of selectionDidChange:.
[self performSelector:@selector(mySelectionDidChange:) withObject:textInput];
// "Do whatever you want" with the selectedText below.
NSString *selectedText = [textInput textInRange:textInput.selectedTextRange];
NSLog(@"selectedText: %@", selectedText);
}
#2
6
I did solve my query as follow :
我确实解决了以下问题:
I implement UITextView's delegate and implement following method
我实现了UITextView的委托并实现了以下方法
- (void)textViewDidChangeSelection:(UITextView *)textView {
NSRange r = textView.selectedRange;
NSLog(@"Start from : %d",r.location); //starting selection in text selection
NSLog(@"To : %d",r.length); // end position in text selection
NSLog([tv.text substringWithRange:NSMakeRange(r.location, r.length)]); //tv is my text view
}
That's it!
就是这样!
#3
2
Swift
In Swift, getting the selected text from a UITextField
is done like this:
在Swift中,从UITextField获取所选文本的操作如下:
if let textRange = myTextField.selectedTextRange {
let selectedText = myTextField.textInRange(textRange)
}
where textRange
is a UITextRange
that is used to get the actual selected text.
其中textRange是用于获取实际选定文本的uitoutange。
#4
1
A similar topic is discussed here: Can I select a specific block of text in a UITextField?
这里讨论了一个类似的主题:我可以在UITextField中选择一个特定的文本块吗?
AFAIK there is no event if text is selected. However, you could setup an NSTimer to watch your textfield and check the _selectedRange
. If it changes, go fire up your text-to-speech code.
如果选择了文本,则没有事件发生。但是,您可以设置一个NSTimer来监视文本字段并检查_selectedRange。如果它改变了,启动你的文本到语音代码。
EDIT: I was wrong about the selection. UITextField cannot do what you want to achieve. But if you use UITextView
instead, you can implement its UITextViewDelegate and override
编辑:我选错了。UITextField不能做您想要实现的事情。但是如果您使用UITextView,您可以实现它的UITextViewDelegate并覆盖它
- (void)textViewDidChangeSelection:(UITextView *)textView
In there, you can use the selectedRange
poperty to get the selection. See this reference for details:
在那里,您可以使用selectedRange poperty来获取选择。详见此参考资料:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextView_Class/Reference/UITextView.html / / apple_ref / doc / uid / TP40006898-CH3-SW13
#5
0
Swift 4
斯威夫特4
for getting the selected UITextField:
获取选定的UITextField:
import UIKit
extension UIView {
func getSelectedTextField() -> UITextField? {
let totalTextFields = getTextFieldsInView(view: self)
for textField in totalTextFields{
if textField.isFirstResponder{
return textField
}
}
return nil
}
func getTextFieldsInView(view: UIView) -> [UITextField] {
var totalTextFields = [UITextField]()
for subview in view.subviews as [UIView] {
if let textField = subview as? UITextField {
totalTextFields += [textField]
} else {
totalTextFields += getTextFieldsInView(view: subview)
}
}
return totalTextFields
}
}
#1
26
-[UITextField selectedText]
Although UITextField
doesn't have a selectedText
method, it conforms to the UITextInput
protocol. So, you can use the required properties & methods of the UITextInput
protocol to determine the selectedText
of a UITextField *textField
(or any object that conforms to the UITextInput
protocol, such as a UITextView
).
虽然UITextField没有selectedText方法,但它符合UITextInput协议。因此,您可以使用UITextInput协议所需的属性和方法来确定UITextField *textField的selectedText(或任何符合UITextInput协议的对象,如UITextView)。
NSString *selectedText = [textField textInRange:textField.selectedTextRange];
NSLog(@"selectedText: %@", selectedText);
As an aside, you can also use the required properties & methods of the UITextInput
to calculate the selectedRange
of a UITextField *textField
.
顺便说一下,您还可以使用UITextInput所需的属性和方法来计算UITextField *textField的selectedRange。
UITextRange *selectedTextRange = textField.selectedTextRange;
NSUInteger location = [textField offsetFromPosition:textField.beginningOfDocument
toPosition:selectedTextRange.start];
NSUInteger length = [textField offsetFromPosition:selectedTextRange.start
toPosition:selectedTextRange.end];
NSRange selectedRange = NSMakeRange(location, length);
NSLog(@"selectedRange: %@", NSStringFromRange(selectedRange));
-[UITextFieldDelegate textFieldDidChangeSelection:]
Although, UITextFieldDelegate
doesn't declare a textFieldDidChangeSelection:
delegate method like -[UITextViewDelegate textViewDidChangeSelection:]
, you can still hook into when the selection of a UITextField
has changed. To do so, subclass UITextField
and use method swizzling to add your own code to the textField.inputDelegate
's native implementation of -[UITextInputDelegate selectionDidChange:]
.
尽管UITextFieldDelegate没有声明textFieldDidChangeSelection:委托方法,比如-[UITextViewDelegate textViewDidChangeSelection:],但是当UITextField的选择发生变化时,您仍然可以继续使用它。为此,子类UITextField和使用方法swizzle将您自己的代码添加到textField。inputDelegate的本机实现-[UITextInputDelegate selectionDidChange:]。
// MyTextField.h
#import <UIKit/UIKit.h>
@interface MyTextField : UITextField
@end
// MyTextField.m
#import <objc/runtime.h>
#import "MyTextField.h"
UIKIT_STATIC_INLINE void mySelectionDidChange(id self, SEL _cmd, id<UITextInput> textInput);
@implementation MyTextField {
BOOL swizzled;
}
#pragma mark - UIResponder
// Swizzle here because self.inputDelegate is set after becomeFirstResponder gets called.
- (BOOL)becomeFirstResponder {
if ([super becomeFirstResponder]) {
[self swizzleSelectionDidChange:YES];
return YES;
} else {
return NO;
}
}
// Unswizzle here because self.inputDelegate may become the inputDelegate for another UITextField.
- (BOOL)resignFirstResponder {
if ([super resignFirstResponder]) {
[self swizzleSelectionDidChange:NO];
return YES;
} else {
return NO;
}
}
#pragma mark - Swizzle -[UITextInput selectionDidChange:]
// Swizzle selectionDidChange: to "do whatever you want" when the text field's selection has changed.
// Only call this method on the main (UI) thread because it may not be thread safe.
- (void)swizzleSelectionDidChange:(BOOL)swizzle {
if (swizzle == swizzled || ![self respondsToSelector:@selector(inputDelegate)]) return; // 4.3
Class inputDelegateClass = object_getClass(self.inputDelegate);
SEL mySelector = @selector(mySelectionDidChange:);
class_addMethod(inputDelegateClass, mySelector, (IMP)mySelectionDidChange, "v@:@");
Method myMethod = class_getInstanceMethod(inputDelegateClass, mySelector);
Method uiKitMethod = class_getInstanceMethod(inputDelegateClass, @selector(selectionDidChange:));
method_exchangeImplementations(uiKitMethod, myMethod);
swizzled = swizzle;
// NSLog(@"swizzled? %i", method_getImplementation(uiKitMethod) == (IMP)venmo_selectionDidChange);
}
@end
UIKIT_STATIC_INLINE void mySelectionDidChange(id self, SEL _cmd, id<UITextInput> textInput) {
// Call the native implementation of selectionDidChange:.
[self performSelector:@selector(mySelectionDidChange:) withObject:textInput];
// "Do whatever you want" with the selectedText below.
NSString *selectedText = [textInput textInRange:textInput.selectedTextRange];
NSLog(@"selectedText: %@", selectedText);
}
#2
6
I did solve my query as follow :
我确实解决了以下问题:
I implement UITextView's delegate and implement following method
我实现了UITextView的委托并实现了以下方法
- (void)textViewDidChangeSelection:(UITextView *)textView {
NSRange r = textView.selectedRange;
NSLog(@"Start from : %d",r.location); //starting selection in text selection
NSLog(@"To : %d",r.length); // end position in text selection
NSLog([tv.text substringWithRange:NSMakeRange(r.location, r.length)]); //tv is my text view
}
That's it!
就是这样!
#3
2
Swift
In Swift, getting the selected text from a UITextField
is done like this:
在Swift中,从UITextField获取所选文本的操作如下:
if let textRange = myTextField.selectedTextRange {
let selectedText = myTextField.textInRange(textRange)
}
where textRange
is a UITextRange
that is used to get the actual selected text.
其中textRange是用于获取实际选定文本的uitoutange。
#4
1
A similar topic is discussed here: Can I select a specific block of text in a UITextField?
这里讨论了一个类似的主题:我可以在UITextField中选择一个特定的文本块吗?
AFAIK there is no event if text is selected. However, you could setup an NSTimer to watch your textfield and check the _selectedRange
. If it changes, go fire up your text-to-speech code.
如果选择了文本,则没有事件发生。但是,您可以设置一个NSTimer来监视文本字段并检查_selectedRange。如果它改变了,启动你的文本到语音代码。
EDIT: I was wrong about the selection. UITextField cannot do what you want to achieve. But if you use UITextView
instead, you can implement its UITextViewDelegate and override
编辑:我选错了。UITextField不能做您想要实现的事情。但是如果您使用UITextView,您可以实现它的UITextViewDelegate并覆盖它
- (void)textViewDidChangeSelection:(UITextView *)textView
In there, you can use the selectedRange
poperty to get the selection. See this reference for details:
在那里,您可以使用selectedRange poperty来获取选择。详见此参考资料:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextView_Class/Reference/UITextView.html / / apple_ref / doc / uid / TP40006898-CH3-SW13
#5
0
Swift 4
斯威夫特4
for getting the selected UITextField:
获取选定的UITextField:
import UIKit
extension UIView {
func getSelectedTextField() -> UITextField? {
let totalTextFields = getTextFieldsInView(view: self)
for textField in totalTextFields{
if textField.isFirstResponder{
return textField
}
}
return nil
}
func getTextFieldsInView(view: UIView) -> [UITextField] {
var totalTextFields = [UITextField]()
for subview in view.subviews as [UIView] {
if let textField = subview as? UITextField {
totalTextFields += [textField]
} else {
totalTextFields += getTextFieldsInView(view: subview)
}
}
return totalTextFields
}
}