如何从 iphone 中的 uitextfield 获取选定的文本?

发布于 2024-10-21 05:07:54 字数 126 浏览 2 评论 0 原文

我正在 iPhone 中开发文本到语音应用程序,

其中有一个接受输入的文本字段,我希望用户从文本字段中选择文本的某些部分,我的应用程序会将所选文本转换为语音。

我的问题是如何获取用户从文本字段中选择的文本?

I am working on Text to speech application in 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

伪心 2024-10-28 05:07:54

-[UITextField selectedText]

虽然 UITextField 没有 selectedText 方法,它符合 UITextInput 协议。因此,您可以使用所需的属性 & UITextInput 协议的方法,用于确定 UITextField *textFieldselectedText(或任何符合 UITextInput 的对象) > 协议,例如 UITextView< /a>)。

NSString *selectedText = [textField textInRange:textField.selectedTextRange];
NSLog(@"selectedText: %@", selectedText);

另外,您还可以使用所需的属性和属性。 UITextInput 的方法来计算 UITextField *textFieldselectedRange

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:]

虽然 UITextFieldDelegate 没有声明 textFieldDidChangeSelection: 委托方法,如 -[UITextViewDelegate textViewDidChangeSelection:],当 UITextField 的选择发生更改时,您仍然可以挂钩。为此,请子类化 UITextField 并使用方法调配将您自己的代码添加到 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);        
}

-[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).

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.

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:].

// 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);        
}
土豪我们做朋友吧 2024-10-28 05:07:54

我确实解决了我的查询,如下所示:

我实现了 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
}

就是这样!

I did solve my query as follow :

I implement UITextView's delegate and implement following method

- (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!

甜味拾荒者 2024-10-28 05:07:54

Swift

在 Swift 中,从 UITextField 获取选定的文本是这样完成的:

if let textRange = myTextField.selectedTextRange {

    let selectedText = myTextField.textInRange(textRange)
    
}

其中 textRange 是用于获取实际选定内容的 UITextRange文本。

Swift

In Swift, getting the selected text from a UITextField is done like this:

if let textRange = myTextField.selectedTextRange {

    let selectedText = myTextField.textInRange(textRange)
    
}

where textRange is a UITextRange that is used to get the actual selected text.

心病无药医 2024-10-28 05:07:54

这里讨论了类似的主题:我可以选择UITextField 中的特定文本块?

AFAIK 如果选择文本,则不会发生任何事件。但是,您可以设置 NSTimer 来监视文本字段并检查 _selectedRange。如果发生变化,请启动文本转语音代码。

编辑:我的选择是错误的。 UITextField 无法实现您想要实现的目标。但是,如果您使用 UITextView,则可以实现其 UITextViewDelegate 并覆盖

- (void)textViewDidChangeSelection:(UITextView *)textView

其中,您可以使用 selectedRange 属性来获取选择。有关详细信息,请参阅此参考:

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextView_Class/Reference/UITextView.html#//apple_ref/doc/uid/TP40006898-CH3- SW13

A similar topic is discussed here: Can I select a specific block of text in a 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.

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

- (void)textViewDidChangeSelection:(UITextView *)textView

In there, you can use the selectedRange poperty to get the selection. See this reference for details:

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextView_Class/Reference/UITextView.html#//apple_ref/doc/uid/TP40006898-CH3-SW13

橘寄 2024-10-28 05:07:54

UITextField 没有委托来获取选择范围更改。我们可以使用 KVO 来观察 UITextfieldselectedTextRange 属性。

    [textField addObserver:self forKeyPath:@"selectedTextRange" options:NSKeyValueObservingOptionNew context:NULL];

或者创建 UITextField 子类并重写 setSelectedTextRange 方法。

UITextField don't have delegate to get the selection range change. We can use KVO to observe selectedTextRange property of UITextfield.

    [textField addObserver:self forKeyPath:@"selectedTextRange" options:NSKeyValueObservingOptionNew context:NULL];

Or create UITextField subclass and override setSelectedTextRange method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文