FirstResponder 释放问题

View的FirstResponder的释放问题

  今天遇到一个问题,当我隐藏掉一个正在接受用户输入的UITextField的时候,键盘并不会消失,而且键盘仍然接受用户输入,再次显示该TextField时候发现在隐藏状态下,所有的输入仍然传输到了该TextField中,于是查下官方资料找到如下解释:

Important If you hide a view that is currently the first responder, the view does not automatically resign its first responder status. Events targeted at the first responder are still delivered to the hidden view. To prevent this from happening, you should force your view to resign the first responder status when you hide it.    

  意思是如果这个View是当前的第一响应者的时候,隐藏该View并不会自动放弃其第一响应者的身份,而且会继续以第一响应者的身份接受消息。我们可以通过在隐藏View之前,手动调用resignFirstResponder来强制该view放弃第一响应者身份。

  下面请看小例子:

SvTestFirstResponder.h
//
// SvTestFirstResponder.h
//
// Created by maple on 3/15/12.
// Copyright (c) 2012 SmileEvday. All rights reserved.
//
// 当一个view时当前响应者时,调用其hidden方法并不会自动放弃第一响应者身份,所有的消息仍然会发送到这个view
// 可以通过在hidden前强制放弃第一响应者,恢复正常的消息传递
//

#import <UIKit/UIKit.h>

@interface SvTestFirstResponder : UIView {
UITextField *_inputField;
}

@end
SvTestFirstResponder.m
//
// SvTestFirstResponder.m
//
// Created by maple on 3/15/12.
// Copyright (c) 2012 SmileEvday. All rights reserved.
//

#import "SvTestFirstResponder.h"

@interface SvTestFirstResponder()

- (void)hiddenInputView:(id)sender;
- (void)showInputView:(id)sender;

@end

@implementation SvTestFirstResponder

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

_inputField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 200, 50)];
_inputField.center = CGPointMake(160, 50);
[_inputField setFont:[UIFont systemFontOfSize:24]];
_inputField.text = @"input you text";
_inputField.clearsOnBeginEditing = YES;
_inputField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
_inputField.borderStyle = UITextBorderStyleRoundedRect;
[self addSubview:_inputField];
_inputField.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;

UIButton *hiddenBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
hiddenBtn.frame = CGRectMake(0, 0, 115, 40);
hiddenBtn.center = CGPointMake(80, 110);
[hiddenBtn setTitle:@"Hide TextField" forState:UIControlStateNormal];
[hiddenBtn addTarget:self action:@selector(hiddenInputView:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:hiddenBtn];
hiddenBtn.autoresizingMask = UIViewAutoresizingFlexibleRightMargin;
hiddenBtn.titleLabel.lineBreakMode = UILineBreakModeTailTruncation;

UIButton *showBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
showBtn.frame = CGRectMake(0, 0, 115, 40);
showBtn.center = CGPointMake(240, 110);
[showBtn setTitle:@"Show TextField" forState:UIControlStateNormal];
[showBtn addTarget:self action:@selector(showInputView:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:showBtn];
showBtn.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
showBtn.titleLabel.lineBreakMode = UILineBreakModeTailTruncation;
}
return self;
}

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/

- (void)hiddenInputView:(id)sender
{
_inputField.hidden = YES;
}

- (void)showInputView:(id)sender
{
_inputField.hidden = NO;
}

@end

  这个简单的例子中,当输入框进入接受用户输入状态的时候,点击hide按钮,键盘并不会消失而且会继续接收用户输入并且将用户输入传到TextField中去,后面再点击Show按钮的时候你会发现所有在隐藏状态下输入的文字都已经成功的被接收。我们可以修改hide方法如下:

- (void)hiddenInputView:(id)sender
{
    if (_inputField.isFirstResponder) {
        [_inputField resignFirstResponder];
    }
    _inputField.hidden = YES;
}

  这样就可以在隐藏之前强制释放第一响应者身份,这个问题比较细节,但有时候可能就是这种细节问题导致一些莫名奇妙的问题,在隐藏一些可能成为第一响应者的view之前添加强制释放第一响应者身份,可能会帮我们避免一些奇怪的问题,而且也几乎不会有什么开销,何乐而不为呢。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Rust的actix-web框架中,`Responder`和`ResponseError`是用于处理HTTP响应的重要trait。它们允许你定义如何将数据转换为HTTP响应以及如何处理错误。 `Responder` trait用于将数据转换为HTTP响应。你可以在自定义的类型上实现`Responder` trait,以便该类型可以直接返回给actix-web的处理器函数。以下是一个示例: ```rust use actix_web::{HttpResponse, Responder}; struct MyData { // 数据结构 } impl Responder for MyData { type Error = actix_web::Error; type Future = Result<HttpResponse, Self::Error>; fn respond_to(self, _: &actix_web::HttpRequest) -> Self::Future { // 将数据转换为HttpResponse let response = HttpResponse::Ok().json(self); // 假设MyData实现了serde的Serialize trait Ok(response) } } ``` 在这个示例中,我们为自定义的`MyData`类型实现了`Responder` trait。我们通过实现`respond_to`方法来定义如何将数据转换为HTTP响应。在这个例子中,我们使用`HttpResponse::Ok().json(self)`将`MyData`转换为JSON格式的HTTP响应。 `ResponseError` trait用于处理错误并生成适当的HTTP响应。你可以在自定义的错误类型上实现`ResponseError` trait,以便actix-web可以捕获并处理这些错误。以下是一个示例: ```rust use actix_web::{HttpResponse, ResponseError}; use std::convert::From; #[derive(Debug)] struct MyError { // 错误信息 } impl ResponseError for MyError { fn error_response(&self) -> HttpResponse { // 生成适当的HTTP响应 HttpResponse::InternalServerError().body("Internal Server Error") } } impl From<actix_web::Error> for MyError { fn from(_: actix_web::Error) -> Self { MyError { // 从actix-web的Error转换为自定义的错误类型 } } } ``` 在这个示例中,我们为自定义的`MyError`类型实现了`ResponseError` trait。我们通过实现`error_response`方法来定义如何生成适当的HTTP响应。在这个例子中,我们直接返回一个带有"Internal Server Error"消息的500错误响应。 另外,我们还实现了`From<actix_web::Error>` trait,以便将actix-web的错误转换为我们自定义的错误类型。这样,在处理请求时,actix-web可以自动将错误转换为我们定义的`MyError`类型。 希望这可以帮助你理解和使用`Responder`和`ResponseError` trait!如果还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值