在UITextField/UIWebView中缺少复制/粘贴菜单

8

我遇到了一个问题,但是找不到解决方法。

我的视图中包含一个UIWebView和一个UITextField。在这两个控件上,当我点击时没有弹出复制/粘贴菜单。

UIWebView中有文本(仅文本),我可以选择单词、段落或者放大镜手动选择所需文本。

UITextField可以输入并正常工作,除了复制/粘贴功能之外。

没有进行子类化。我只需要iOS默认的复制/粘贴功能实现。

这个问题不仅出现在一个视图中。我在另一个UIWebView中也遇到了同样的问题,所以我认为这是一个全局性的问题。

我已经尝试过所有明显的方法(导入UIKit和Foundation框架、分配属性、释放等),但是我还是卡在这里了。

是什么因素影响/干扰了这个简单的功能,禁用了它? 此外,在最简单的实现下,还需要什么才能使其正常工作?(是否缺少任何框架、属性等)。

这是一件非常简单的事情,但我卡在这里了。 如果有人有任何想法,将不胜感激。

==== 编辑 ====

这个问题并不是由我的代码在任何视图或类中引起的。

我添加了一个新视图(应用程序基于选项卡),其中只包含一个UITextField和一个带有默认“Lorem Ipsum”文本的UITextView。在textView中,我也可以选择文本,但没有复制/粘贴/选择/全选菜单出现。这也发生在textField(空)中,没有粘贴菜单出现(我从另一个应用程序(如Safari或Notes)中复制一些文本)。

似乎这个问题影响到了整个应用程序中的所有视图。

我已经删除了框架引用并重新添加了它们,但仍然没有任何进展。 我仍在努力寻找问题所在。

5个回答

10

我遇到了相同的问题 - 所有其他功能都可以正常使用,但所有应用程序中的 UITextView 都缺少“复制/粘贴/选择”菜单。

经过一些尝试,我发现原因可能是:

在MainWindow.xib中的窗口上未设置“Visible at Launch”属性

或者

在AppDelegate的application:didFinishLaunchingWithOptions:方法中没有调用[self.window makeKeyAndVisible]

在修复了其中任何一个问题之后,它就能正常工作。 试试看吧。


如果您是在Xcode 3中创建项目,那么它也需要makeKeyandVisible。非常感谢。 - zambono
刚碰到了这个问题。[window makeKeyAndVisible] 解决了它。伟大的侦探工作! - jsd
这对我的情况没有帮助。 - Zaporozhchenko Oleksandr

7

如果你在处理 Xcode 11+ 和 iOS 13+ 的项目(以及 SceneDelegate),请确保按照以下精确顺序进行更改:

import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?


    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = (scene as? UIWindowScene) else { return }
        window = UIWindow()
        window!.rootViewController = rootNavigation
        window!.windowScene = windowScene
        window!.makeKeyAndVisible()
    }
}

因为,如果你将它应用在类似这样的地方:

    window!.makeKeyAndVisible()
    window!.windowScene = windowScene

你描述了一个问题,它看起来很好,工作正常,但复制粘贴操作不会出现。我花了一段时间才发现这一点。


1
谢谢。这解决了问题。你太棒了! - John Doe
这是正确的答案。有人知道为什么这样修复了问题吗? - Peter Suwara
该死,这下修好了。仿真器似乎不在意顺序,所以我只在我的设备上看到了问题。我真的很高兴你找到了解决方法,也很好奇你是如何找到它的。 - laka

1

请确保您实现了以下内容:

//init your menu somewhere, appropiately

- (id) initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {

        NSMutableArray *items = [[[UIMenuController sharedMenuController] menuItems] mutableCopy];
        if (!items) items = [[NSMutableArray alloc] init];

        UIMenuItem *menuItem;
        menuItem = [[UIMenuItem alloc] initWithTitle:@"Undo" action:@selector(undo:)];
        [items addObject:menuItem];
        [menuItem release];
        menuItem = [[UIMenuItem alloc] initWithTitle:@"Redo" action:@selector(redo:)];
        [items addObject:menuItem];
        [menuItem release];

        [[UIMenuController sharedMenuController] setMenuItems:items];
            [items release];

    }
    return self;
}

//allow other items to appear and yours too :) Perhaps you are missing this?
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    if ([super canPerformAction:action withSender:sender]) {
        return YES;
    }
    else {
        //write your code here
        if (action == @selector(undo:) && [self.undoManager canUndo]) return YES;
        if (action == @selector(redo:) && [self.undoManager canRedo]) return YES;
    }
    return NO;
}

//Do your actions 
- (void)undo:(id)sender{
//do your stuff here
}
- (void)redo:(id)sender{
//do your stuff here
}

我已经尝试了canPerformAction:(alone),但没有结果。在initWithFrame中,self = [super initWithFrame:frame]会产生一个警告UIViewController可能无法响应。 - Pericles
仅供完成目的,此代码应编写在您要显示菜单的视图中。而不是UIViewController中。(由于您没有对任何内容进行子类化,因此您不需要这个,抱歉我误读了一些内容) - nacho4d

0

好的,我找到了解决方案。 这与代码或对象的属性无关。 这更多地是XCode4的“实现”。

当创建一个新的通用项目时,xcode会将一个AppDelegate放在项目的根目录下,并在每个文件夹中放置另外两个AppDelegate,一个用于iPad,另一个用于iPhone。

根App Delegate看起来像:

#import <UIKit/UIKit.h> 
@interface SampleAppDelegate : NSObject <UIApplicationDelegate> { }
@property (nonatomic, retain) IBOutlet UIWindow *window;

使用

#import "SampleAppDelegate.h"
@implementation SampleAppDelegate
@synthesize window=_window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
    [self.window makeKeyAndVisible];
    return YES;
}
- (void)dealloc
{
    [_window release];
    [super dealloc];
}
@end

iPhone和iPad应用程序的委托没有“窗口”引用。

如果根AppDelegate被删除并且“window”代码移动到每个特定于设备的AppDelegate中,则选择/全选/复制/粘贴(或任何其他选项)菜单将再次出现。

这在我创建的第一个新xcode4上发生了。我不太记得xcode3是否有类似的实现(但我认为没有)。


你找到了不删除根代理的解决方案吗?我已经将我的窗口移动到iPhone / iPad代理,但仍然看不到复制和粘贴。 - zambono
我没有进一步尝试过。通过这样做,我解决了其他问题(例如iPad键盘底部右侧的“隐藏键盘”按钮开始工作)。我认为这是因为该项目最初是在xcode3上创建的,在经过Xcode4后留下了一些东西(可能是这个原因)。我假设在xcode4上创建的新项目不会有问题。这是一个非常奇怪的情况,这个解决方案或多或少是一个解决方法。 - Pericles

0

看起来,现在(2020年)iOS中存在一个bug。当您将UITextField的对齐方式更改为居中(NSTextAlignmentCenter)时,您无法触发像粘贴空字段之类的操作。

也许这也是您的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接