在 UITextField 之外的任何地方触摸时关闭键盘

2023-12-12

我正在开发一个iPad应用程序,其中有大量UIViewControllers, UITableViews(与细胞accessoryViews of UITextFields)等等等等。许多UIViewControllers出现在导航层次结构中。

有很多不同的地方UITextFields出现,包括作为UITableViewCell accessoryViews.

我想设计一种有效的策略,每当用户触摸键盘之外时就关闭键盘UITextField目前正在编辑中。我已经搜索了键盘关闭技术,但尚未找到解释通用键盘关闭策略如何工作的答案。

例如,我喜欢这种方法,将以下代码添加到任何 ViewController 中:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"* * * * * * * * *ViewControllerBase touchesBegan");

    [self.view endEditing:YES]; // dismiss the keyboard

    [super touchesBegan:touches withEvent:event];
}

...但是该技术不能处理例如触摸发生在一个区域内的情况。UITableView正在展出。所以,我需要添加一些代码来调用endEditing when a UITableView被触摸等,等等。这意味着我的应用程序将大量散布大量代码,以在其他各种情况下关闭键盘UIElements被感动了。

我想我可以尝试识别需要拦截触摸和关闭键盘的所有不同位置,但在我看来,可能有更好的设计模式来处理 iOS 键盘关闭事件。

任何人都可以分享他们在这方面的经验,并推荐一种特定的技术来一般处理整个应用程序中的键盘关闭吗?

非常感谢


你的视图层次结构位于UIWindow. The UIWindow负责将触摸事件转发到其正确的视图sendEvent:方法。让我们创建一个子类UIWindow覆盖sendEvent:.

@interface MyWindow : UIWindow
@end

该窗口将需要对当前第一响应者的引用(如果有)。您可能决定也使用UITextView,因此我们将观察来自文本字段和文本视图的通知。

@implementation MyWindow {
    UIView *currentFirstResponder_;
}

- (void)startObservingFirstResponder {
    NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
    [center addObserver:self selector:@selector(observeBeginEditing:) name:UITextFieldTextDidBeginEditingNotification object:nil];
    [center addObserver:self selector:@selector(observeEndEditing:) name:UITextFieldTextDidEndEditingNotification object:nil];
    [center addObserver:self selector:@selector(observeBeginEditing:) name:UITextViewTextDidBeginEditingNotification object:nil];
    [center addObserver:self selector:@selector(observeEndEditing:) name:UITextViewTextDidEndEditingNotification object:nil];
}

- (void)stopObservingFirstResponder {
    NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
    [center removeObserver:self name:UITextFieldTextDidBeginEditingNotification object:nil];
    [center removeObserver:self name:UITextFieldTextDidEndEditingNotification object:nil];
    [center removeObserver:self name:UITextViewTextDidBeginEditingNotification object:nil];
    [center removeObserver:self name:UITextViewTextDidEndEditingNotification object:nil];
}

- (void)observeBeginEditing:(NSNotification *)note {
    currentFirstResponder_ = note.object;
}

- (void)observeEndEditing:(NSNotification *)note {
    if (currentFirstResponder_ == note.object) {
        currentFirstResponder_ = nil;
    }
}

窗口将在初始化时开始观察通知,并在释放时停止:

- (id)initWithCoder:(NSCoder *)aDecoder {
    if ((self = [super initWithCoder:aDecoder])) {
        [self commonInit];
    }
    return self;
}

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

- (void)commonInit {
    [self startObservingFirstResponder];
}

- (void)dealloc {
    [self stopObservingFirstResponder];
}

我们将覆盖sendEvent:根据事件“调整”第一响应者,然后调用超级的sendEvent:正常发送事件。

- (void)sendEvent:(UIEvent *)event {
    [self adjustFirstResponderForEvent:event];
    [super sendEvent:event];
}

如果没有第一响应者,我们不需要对第一响应者做任何事情。如果有第一响应者,并且它包含触摸,我们不想强迫它辞职。 (请记住,可以同时有多个触摸!)如果有第一响应者,并且新的触摸出现在可以成为第一响应者的另一个视图中,系统将自动正确处理该情况,因此我们也想忽略这种情况。但是,如果有第一响应者,并且它不包含任何触摸,并且新触摸出现在视图中,can't成为第一响应者,我们想让第一响应者辞职。

- (void)adjustFirstResponderForEvent:(UIEvent *)event {
    if (currentFirstResponder_
        && ![self eventContainsTouchInFirstResponder:event]
        && [self eventContainsNewTouchInNonresponder:event]) {
        [currentFirstResponder_ resignFirstResponder];
    }
}

报告事件是否包含第一响应者中的触摸很容易:

- (BOOL)eventContainsTouchInFirstResponder:(UIEvent *)event {
    for (UITouch *touch in [event touchesForWindow:self]) {
        if (touch.view == currentFirstResponder_)
            return YES;
    }
    return NO;
}

报告事件是否在视图中包含无法成为第一响应者的新触摸几乎同样简单:

- (BOOL)eventContainsNewTouchInNonresponder:(UIEvent *)event {
    for (UITouch *touch in [event touchesForWindow:self]) {
        if (touch.phase == UITouchPhaseBegan && ![touch.view canBecomeFirstResponder])
            return YES;
    }
    return NO;
}

@end

实现此类后,您需要更改应用程序以使用它而不是UIWindow.

如果您正在创建您的UIWindow in application:didFinishLaunchingWithOptions:, 你需要#import "MyWindow.h"在你的顶部AppDelegate.m,然后改变application:didFinishLaunchingWithOptions:创建一个MyWindow代替UIWindow.

如果您正在创建您的UIWindow在笔尖中,您需要将窗口的自定义类设置为MyWindow在笔尖。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 UITextField 之外的任何地方触摸时关闭键盘 的相关文章

  • 如何让 Chrome Cast 在 iOS 后台运行?

    我有一个简单的问题 当您进入 iPhone 的主屏幕并且不退出应用程序时 chrome Cast 设备会停止在屏幕上播放视频 当应用程序在后台运行时 我如何才能保持播放状态 如果您有一个视频应用程序并且它在投射设备中运行 您可能需要以下行为
  • iOS-将图像转为视频时,CVPixelBufferCreate内存无法正确释放

    我正在将图像制作成视频 但总是因为内存警告而崩溃 分配太多CVPixelBufferCreate 我不知道如何正确处理 我看过很多类似的主题 但没有一个能解决我的问题 这是我的代码 void writeImagesArray NSArray
  • 将 .p12 证书存储在钥匙串中以供稍后使用

    我正在尝试按照 Apple 文档处理此处的客户端 p12 证书 https developer apple com library ios documentation Security Conceptual CertKeyTrustProg
  • Draggable Boxview 不更新 Xamarin

    我的第一个问题是框视图生成在左上角 而不是我指定的设计网格第 10 行和网格第 3 列 第二个问题在于可拖动视图 在代码本地可拖动视图的第一部分中 它正确地调用了触摸事件 但也许它没有在GUI中更新
  • 与自定义键盘扩展进行通信,主机应用程序无法在设备中运行,但可以在模拟器中运行

    我正在使用自定义键盘扩展 这几乎完成了 但当我与扩展和我的主机应用程序通信数据时 我只是面临设备问题 该应用程序在设备中没有工作 但在模拟器中工作也是如此 我的代码如下 HostApp 视图控制器 void viewDidLoad defa
  • 定位精度定义 - iOS

    iOS 上返回的 准确性 或 不确定性 的统计意图是什么 即使是近似值 例如 Android 文档对其返回的精度数字进行了解释 从这个意义上讲 它大约是一个标准差 我们将准确度定义为 68 置信度的半径 换句话说 如果 您以该位置的纬度和经
  • 添加 AFNetworking 后出现 APPLE MACH-O 链接错误

    只是将 AFNetworking 添加到我的项目中 在 B R 后 我收到如下错误 Undefined symbols for architecture i386 SecCertificateCopyData referenced from
  • “EXC_BAD_ACCESS”与“分段错误”。两者实际上相同吗?

    在我的前几个虚拟应用程序 用于学习时练习 中 我遇到了很多EXC BAD ACCESS 这以某种方式告诉我错误访问是 您正在触摸 访问一个不应该的对象 因为它尚未分配或释放 或者只是您无权访问它 查看此示例代码 该代码存在访问错误问题 因为
  • 设置UITextField的光标位置

    我查看了单点触控示例并尝试过 var range new NSRange selectionStart 1 NumberTextField SelectedTextRange IndexedRange GetRange range 但这会在
  • iOS - 在 UITabBar 上方获取所需的阴影

    我试图让我的标签栏阴影看起来像这张图片中看到的那样 这样做的最佳方法是什么 我正在使用 Objective C Thanks 您可以使用以下代码为任何 UI 对象提供阴影 tabBar layer shadowOffset CGSize w
  • 是否可以对 UILabel 的文本颜色变化进行动画处理? [复制]

    这个问题在这里已经有答案了 UIView animateWithDuration 5 animations myLabel textColor UIColor redColor 标签文本颜色立即改变 Try this UIView tran
  • 在两个可移动 uiview 之间画线

    我有一个带有节点的 滚动视图 UIViews 可以拖动 我正在尝试在选定的之间绘制边缘UIViews使用 calayer 但我不知道当视图位置发生变化时如何重新绘制线条 In my viewControllerI 类在节点数组中添加第一个和
  • 使用基于 Cookie 的身份验证的 Capacitor iOS

    我正在使用 Capacitor v3 NextJS 静态导出和 Django 后端基于生产网站构建 iOS 应用程序 当前的后端身份验证方案通过 cookie 使用 Django 会话 并通过 cookie 设置 CSRF 令牌 应用程序可
  • 如何在 iOS 应用程序中检测所有可用的 Wifi 网络并连接到其中之一

    在我的 iOS 应用程序中 我想检测所有可用的 wifi 网络 然后从列表中选择一个网络并连接到它 目标是不打开应用程序内置的设置来连接 Wi Fi 而是在我的应用程序中完成这一切 首先 这可能吗 如果可能的话 请指出要使用哪些框架和方法
  • 使用 UIWebView 显示 PDF 不起作用

    因此 我意识到有关使用 UIWebView 在应用程序 在 iPad 上 中显示 PDF 存在很多问题 我已经审查了我能找到的所有内容 但似乎找不到任何满意的东西 我想做的事情非常基本 所以我真的不知道为什么它不起作用 我需要做的就是在 U
  • 如何在多个视图中显示相同的导航栏?

    我可以为一个视图重现以下导航栏 但是 一旦我单击按钮后移至下一个视图 我就会丢失最右边的两个图标 搜索 个人资料 据我所知 从故事板设置导航项目通常是按视图进行的 我可以为每个视图复制这些项目 但我想知道是否有更好的方法来完成一次 是否有教
  • 如何将NSTextView的格式化内容转换为字符串

    我需要将 NSTextView 的内容从 Mac 应用程序传输到 iOS 应用程序 我使用 XML 作为传输文件格式 所以我需要将 NSTextView 的内容 文本 字体 颜色等 保存为字符串 有什么办法可以做到这一点吗 一种方法是存档
  • 使用自定义格式将字符串转换为 NSDate [重复]

    这个问题在这里已经有答案了 可能的重复 NSString 到 NSDate https stackoverflow com questions 1353081 nsstring to nsdate iPhone 如何将 yyyyMMddTh
  • 如何删除以前的 ViewController

    我是一名学生 对编程还很陌生 我正在尝试在业余时间学习 Objective C Swift 我使用 spriteKit 和 swift 制作了一个游戏 有多个菜单 场景 我正在尝试从一个视图控制器转换到另一个视图控制器 为此 我使用了以下代
  • 构建 iOS 应用程序后退出代码 1 错误

    我正在尝试使用 RestKit 构建我的项目 当我构建它时 我收到以下错误 我尝试使用 Apple LLVM 3 0 和 LLVM GCC 4 2 进行编译 两者都产生相同的结果 任何人有任何想法是什么导致了这个问题 Ld Users Ji

随机推荐