登录界面UITextField在API响应后自动弹出键盘问题求助
解决登录后键盘自动弹出的问题
看起来你的问题出在同步网络请求阻塞主线程,加上UI操作的时机不对,导致之前的endEditing:YES没有真正生效,或者请求完成后文本框意外重新获得焦点。我来一步步帮你修复:
问题根源分析
- 同步请求阻塞主线程:你使用的
[NSURLConnection sendSynchronousRequest:]是同步方法,会卡住主线程。这意味着[self.view endEditing:YES]的UI更新被延迟,甚至在请求完成后,系统可能因为主线程刚恢复,错误地让文本框重新成为第一响应者。 - performSelector延迟的副作用:虽然
afterDelay:0.01很短,但主线程被同步请求卡住后,这个延迟执行的方法会和键盘收起的操作产生时机冲突。 - UIAlertView的交互影响:当用户点击Alert的"Ok"按钮时,如果没有明确控制第一响应者,系统可能自动让之前的文本框重新获取焦点,导致键盘弹出。
解决方案
1. 替换同步请求为异步请求(核心修复)
同步请求是iOS开发的大忌,不仅会导致键盘问题,还会让App在请求期间完全无响应。我们用NSURLSession(苹果推荐的网络API,NSURLConnection已废弃)来实现异步请求:
- (void)API_Login { NSString *userEmail = _TXT_email.text; NSString *userPWD = _TXT_password.text; // 主动让文本框放弃第一响应者,确保键盘收起 [_TXT_email resignFirstResponder]; [_TXT_password resignFirstResponder]; NSString *post = [NSString stringWithFormat:@"username=%@&password=%@",userEmail,userPWD]; NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]; NSString *postLength = [NSString stringWithFormat:@"%lu",(unsigned long)[postData length]]; NSString *urlGetuser =[NSString stringWithFormat:@"%@loginApi",SERVER_URL]; NSURL *urlProducts=[NSURL URLWithString:urlGetuser]; NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:urlProducts]; [request setHTTPMethod:@"POST"]; [request setValue:postLength forHTTPHeaderField:@"Content-Length"]; [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:postData]; [request setHTTPShouldHandleCookies:NO]; // 用NSURLSession发起异步请求 NSURLSession *session = [NSURLSession sharedSession]; NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { // 所有UI操作必须回到主线程执行 dispatch_async(dispatch_get_main_queue(), ^{ [activityIndicatorView stopAnimating]; VW_overlay.hidden = YES; if (data) { NSError *jsonError; NSMutableDictionary *json_DATA = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError]; if (!jsonError) { NSLog(@"The response %@",json_DATA); if ([[json_DATA valueForKey:@"status"]isEqualToString:@"success"]) { [[NSUserDefaults standardUserDefaults] setValue:[json_DATA valueForKey:@"driver_id"] forKey:@"driver_id"]; [[NSUserDefaults standardUserDefaults] synchronize]; // 用UIAlertController替代已废弃的UIAlertView(iOS8+推荐) UIAlertController *alert = [UIAlertController alertControllerWithTitle:[json_DATA valueForKey:@"status"] message:[json_DATA valueForKey:@"msg"] preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { // 点击Ok后再跳转页面,避免交互干扰 [self order_details_page]; }]; [alert addAction:okAction]; [self presentViewController:alert animated:YES completion:nil]; } else { UIAlertController *alert = [UIAlertController alertControllerWithTitle:[json_DATA valueForKey:@"status"] message:[json_DATA valueForKey:@"msg"] preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:nil]; [alert addAction:okAction]; [self presentViewController:alert animated:YES completion:nil]; } } else { NSLog(@"JSON解析错误:%@", jsonError); // 可添加解析错误提示 } } else { NSLog(@"Error %@\nResponse %@",error,response); // 可添加网络错误提示 } }); }]; [task resume]; }
2. 调整初始调用逻辑
去掉performSelector:afterDelay,直接调用API_Login,因为异步请求不会阻塞主线程,键盘收起的操作会立即生效:
[self.view endEditing:YES]; VW_overlay.hidden = NO; [activityIndicatorView startAnimating]; [self API_Login]; // 直接调用,无需延迟
3. 额外保障:跳转页面时再次确认键盘收起
在页面跳转前再执行一次键盘收起操作,彻底避免键盘跟随页面切换弹出:
-(void)order_details_page { [self.view endEditing:YES]; [self performSegueWithIdentifier:@"login_order" sender:self]; }
修复逻辑说明
- 异步请求不会阻塞主线程,
endEditing:YES能立即生效,键盘正常收起。 - 所有UI操作都在主线程执行,避免线程冲突导致的UI异常。
- 在Alert的点击回调里触发页面跳转,确保用户交互完成后再执行切换,不会触发文本框重新获取焦点。
内容的提问来源于stack exchange,提问作者Jayasabeen Appukuttan
相关产品推荐
相关产品推荐

