如何以编程方式使文本可选择并提供弹出菜单以转到另一个应用程序

Posted

技术标签:

【中文标题】如何以编程方式使文本可选择并提供弹出菜单以转到另一个应用程序【英文标题】:How to programmatically make text selectable and provide popup menus to go to another app 【发布时间】:2014-07-02 02:46:24 【问题描述】:

我正在尝试在 ios 项目中实现一个功能,当您选择一段文本并突出显示它时,您可以从菜单选项中选择使用另一个应用程序,如默认字典。是否有可能做到这一点?如果是这样,我在哪里可以找到这样的文档或教程?

【问题讨论】:

developer.apple.com/library/ios/documentation/userexperience/… @Pang 请提供一些有用的建议,而不是发布一般信息的链接。在我问这个问题之前,我实际上阅读了有关文本编程指南的整篇文章。 1.你要文件,所以我给了文件。 2. 您的问题有 2 个部分 - 使文本可选择,并提供自定义选项。您可以向我们展示相关代码和/或告诉我们您遇到问题的部分。 @Pang 好的,谢谢。我会继续在这里发布相关的源代码,以防我将来遇到问题。 到目前为止,您已经尝试过 what 了吗?懒惰。 【参考方案1】:

您正在描述 iOS 菜单。查看有关 UIMenu、UIMenuItem 和 UIMenuController 等类的文档。

【讨论】:

在线查看我的示例,例如在文本字段中进行选择的示例:apeth.com/iOSBook/ch23.html#_the_text_field_menu【参考方案2】:

我找到了解决问题的方法。 感谢这篇文章的作者: http://blog.studiovillegas.com/2014/02/06/ios-uipasteboard-uimenucontroller-and-uimenuitem/

将自定义菜单项添加到默认菜单控制器。

ViewController.h

- (void)longPressGestureRecognizer:(UIGestureRecognizer *)recognizer

    UIMenuItem *mi = [self.label menuItemOpenPleco];
    UIMenuController *menuController = [UIMenuController sharedMenuController];
    menuController.menuItems = @[mi];

PasteboardLabel h,m

@interface PasteboardLabel : UILabel

- (UIMenuItem *)menuItemOpenPleco;

@end

@implementation PasteboardLabel

- (UIMenuItem *)menuItemOpenPleco

    return [[UIMenuItem alloc] initWithTitle:@"Open Pleco" action:@selector(openPleco:)];


- (void)openPleco:(id)sender

    NSString *selectedText = [self textInRange:[self selectedTextRange]];
    UIPasteboard *pb = [UIPasteboard generalPasteboard];
    pb.string = selectedText;
    NSString *urlString = [NSString stringWithFormat:@"plecoapi://x-callback-url/q?s=%@", pb.string];
    NSURL *url = [[NSURL alloc] initWithString:urlString];

    [[UIApplication sharedApplication] openURL:url];



@end

【讨论】:

【参考方案3】:

我发现很少有添加自定义菜单项的示例或对其工作方式的说明。所以我想通过分享一些重要的花絮然后展示一个例子来解决这个问题。

    UIMenuControllerUIViews“交谈”,而不是与UIViewControllers。这意味着您的UIMenuController 相关代码需要进入UIView 的子类,而不是UIViewController。 请注意我之前示例开头的词The。只有一个UIMenuController,这是一个从您的应用程序首次启动到结束时共享的单例。这意味着您应该只添加一次您的项目,并且您不应该覆盖现有的项目数组。 UIMenu 中按钮的外观取决于被点击的UIView 是否响应选择器。这意味着如果您希望按钮出现,则需要实现该方法,并且您无需担心在点击不相关视图时它会出现,除非您选择其他 UIView 也有方法的选择器名称。

所以,说了这么多,我创建了一个 UITextView 的子类(这意味着根据我的第一个项目符号它是 UIView 的子类),然后我给了它这个 initialize 方法,以及一个实现我的选择器。

+ (void)initialize 
    static dispatch_once_t addInsert;
    dispatch_once(&addInsert, ^
        UIMenuController *mController = [UIMenuController sharedMenuController];
        UIMenuItem *insert = [[UIMenuItem alloc] initWithTitle:@"Insert..."
                                                        action:@selector(insert:)];
        mController.menuItems = [mController.menuItems arrayByAddingObject:insert];
    );


- (void)insert:(id)sender 
    NSLog(@"Insert... pressed!");

这里的重点:

    它在类initialize 方法中,在第一次调用类中的任何其他方法之前由运行时调用。实际上,这意味着代码是在您的自定义视图实例第一次出现在屏幕上之前处理的。 我在它周围添加了一个dispatch_once 守卫。如果我的类是子类,那么这些子类可能会调用这个initialize 方法。也许这些子类出现在这个之前,所以我不想阻止 initialize 方法运行。我只是想防止它运行多次。因此,我将代码包装在 dispatch_once 中。 我不只是将 menuItems 设置为新的项目数组 - 我将它分配给了一个新的项目数组,该数组用我的新项目扩展了现有的项目数组。

希望所有这些对您有所帮助。这不是很复杂,你当然可以用其他方式来实现我的第二点——我尝试选择一种对我来说似乎最安全的方式,但肯定有更简单的方法。

【讨论】:

以上是关于如何以编程方式使文本可选择并提供弹出菜单以转到另一个应用程序的主要内容,如果未能解决你的问题,请参考以下文章

NSMenu 以编程方式选择项目

单击按钮以转到从 Spinner 选择的下一个活动时出错

如何在初始 mousedown 事件后取消文本选择?

简单的提交表单以转到页面

如何移动文件到另一个文件夹

如何以编程方式将数据从表视图控制器传递到另一个控制器? [复制]