在 ios 8.3 及更高版本中,UIAlertView 导致 keyboardWillShow & keyboardWillHide 调用了两次
Posted
技术标签:
【中文标题】在 ios 8.3 及更高版本中,UIAlertView 导致 keyboardWillShow & keyboardWillHide 调用了两次【英文标题】:In ios 8.3 and later, UIAlertView cause keyboardWillShow & keyboardWillHide called twice 【发布时间】:2015-08-28 07:03:38 【问题描述】:在做项目时,我遇到了这个问题。
其中一个控制器实现keyboardWillShow
和keyboardWillHide
(来自Apple 的标准代码Managing the Keyboard)。
在后台点击时,UIAlertView
出现(基于一些验证),UIAlertView
中只有一个按钮可以简单地关闭UIAlertView
。
问题出现在这里,UIAlertView
关闭时,keyboardWillShow
和 keyboardWillHide
再次调用。
下面是我遇到问题的代码,
#import "ViewController.h"
@interface ViewController () <UITextFieldDelegate>
int timeCalledShow;
int timeCalledHide;
@property (weak, nonatomic) IBOutlet UITextField *textField;
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
- (IBAction)backgroundTapped:(id)sender;
@end
@implementation ViewController
- (void)viewDidLoad
[super viewDidLoad];
//
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardDidHideNotification
object:nil];
- (void)keyboardWillShow:(NSNotification *)notification
timeCalledShow+=1;
NSLog(@"show Time Called %d", timeCalledShow);
CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets;
if (UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation]))
contentInsets = UIEdgeInsetsMake(0.0, 0.0, (keyboardSize.height), 0.0);
else
contentInsets = UIEdgeInsetsMake(0.0, 0.0, (keyboardSize.width), 0.0);
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;
- (void)keyboardWillHide:(NSNotification *)notification
timeCalledHide+=1;
NSLog(@"Hide Time Called %d", timeCalledShow);
self.scrollView.contentInset = UIEdgeInsetsZero;
self.scrollView.scrollIndicatorInsets = UIEdgeInsetsZero;
- (void)didReceiveMemoryWarning
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
- (IBAction)backgroundTapped:(id)sender
[[[UIAlertView alloc] initWithTitle:@"Testing" message:@"Keyboard hide & show, due to alert view" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil] show];
[self.view endEditing:YES];
@end
备注
-
我已经在这里查看keyboardWillShow called twice 和类似问题,但找不到答案
与
ios 7.0
配合使用效果很好
这里是Test Code的链接
编辑
我已经知道代码的工作了。但真正的问题是,UIAlertView
如何触发keyboardWillShow
通知
编辑代码 我已经尝试过@Chonch也建议的下面的代码,但是这个代码键盘甚至永远不会关闭。表示关闭警报后键盘再次出现。
- (IBAction)backgroundTapped:(id)sender
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"testing" message:@"Keyboard" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) ];
[alert addAction:defaultAction];
[self presentViewController:alert animated:YES completion:nil];
[self.textField resignFirstResponder];
Question Posted at Apple Developer Forums
【问题讨论】:
UIAlertView 从 iOS8.0 开始被弃用:developer.apple.com/library/prerelease/ios/documentation/UIKit/… 这可能对***.com/questions/30340531/…有帮助 @AbdAl-rhmanTaherBadary 我已经检查过了,但它没有提供任何解决方案。我需要知道警报视图行为背后的原因。 @pawan 它提供了一个解决方案,您可以在显示警报视图之前取消订阅键盘通知,并在您关闭警报视图后再次订阅,无论如何这里是另一个***.com/questions/30498972/… 好吧,因为它已被弃用,任何事情都可能发生,但这肯定是一个错误,但这是一个很好的观察,尽管***.com/questions/30498972/… 【参考方案1】:UIAlertView 有问题,可能自从它被弃用后就没有了。 将其替换为 UIAlertController
,您的问题应该会消失
【讨论】:
我认为您没有看到编辑代码部分。请在发布任何答案之前检查它。 你能说得更具体点吗?【参考方案2】:不知道为什么会这样。它可能与 UIAlertView 试图将键盘状态恢复到以前的状态有关。但请注意,额外的显示/隐藏调用不会造成任何伤害。通常,无论如何,您都需要为多个演出电话做好准备,因为它们也会在键盘样式更改时出现。
如果您想摆脱它们,请改用 UIAlertController,正如 Chonch 已经建议的那样,并确保在警报出现之前 关闭键盘,然后它会正常工作:
- (IBAction)backgroundTapped:(id)sender
[self.textField resignFirstResponder];
alert = [UIAlertController alertControllerWithTitle:@"testing" message:@"Keyboard" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) ];
[alert addAction:defaultAction];
[self presentViewController:alert animated:YES completion:nil];
请注意,使用 UIAlertController,您还需要在视图控制器中保留对警报的引用,否则它会很快被释放。
【讨论】:
【参考方案3】:我刚刚修复了一个类似的问题。警报消失后键盘继续弹出 好像是苹果的bug。
有一个简单的解决方案: 如果您使用的是 AlertController,则只需将动画设置为 NO
[self presentViewController:alert animated:NO completion:nil];
如果它解决了您的问题,请告诉我
【讨论】:
以上是关于在 ios 8.3 及更高版本中,UIAlertView 导致 keyboardWillShow & keyboardWillHide 调用了两次的主要内容,如果未能解决你的问题,请参考以下文章
UISlider 上的 resizableImageWithCapInsets 在 iOS 6 及更高版本中失真
AVKit.AVPlayerViewController - 控件在 iOS11 及更高版本中不可见
如果 registerForRemoteNotificationTypes: 在 iOS 8.0 及更高版本中不支持,则为 iOS 构建