是否可以在不隐藏键盘的情况下使 UITextView 处于非活动状态(可编辑 = 否)?
Posted
技术标签:
【中文标题】是否可以在不隐藏键盘的情况下使 UITextView 处于非活动状态(可编辑 = 否)?【英文标题】:Is it possible to make UITextView inactive (editable = NO) without hiding the keyboard? 【发布时间】:2012-08-13 19:06:45 【问题描述】:我在 UIViewController 的子类中使用 UITextView,我将其命名为 FacebookPostViewController。所以文本视图的目的是允许用户查看准备好的帖子的内容,可能对其进行更改,然后决定是否应该将来自文本视图的文本发布到 Facebook。
我已将 UITextView 的 returnKeyType 属性设置为 UIReturnKeySend,因为我想用它来实际发布到 Facebook。可以通过导航栏中的后退按钮取消。
所以 FacebookPostViewController 是 UITextView 的委托,在 textView:shouldChangeTextInRange:replacementText: 委托方法中,我检查换行符插入,然后调用我的 sendTextToFacebook 方法:
- (void)sendTextToFacebook;
// prepare sending
NSMutableDictionary* sendParameters = [NSMutableDictionary dictionaryWithObjectsAndKeys:self.textView.text, @"message", nil];
// request sending to own feed
[[FacebookController sharedFacebookController].facebook requestWithGraphpath:@"me/feed" andParams:sendParameters andHttpMethod:@"POST" andDelegate:self];
如你所见,我将self指定为FBRequestDelegate,所以我也实现了
- (void)request:(FBRequest *)request didFailWithError:(NSError *)error;
- (void)request:(FBRequest *)request didLoad:(id)result;
如果发布成功与否,我会在哪里向用户提供反馈。
但是,我认为 Facebook 服务器回复需要一些时间,因此我希望在调用两个委托方法之一之前让整个 UI 处于非活动状态。因此,我实现了以下方法:
- (void)disableUserInterface;
self.textView.editable = NO;
self.loginButton.enabled = NO;
self.logoutButton.enabled = NO;
[self.navigationItem setHidesBackButton:YES animated:YES];
[self.spinner startAnimating];
self.spinner.hidden = NO;
我的问题是调用 self.textView.editable = NO 会隐藏键盘,这看起来很愚蠢。如果我删除该行,键盘不会消失,但用户可以在将文本发送到 Facebook 时更改 textView 内容。但是,由于发布已经启动。这些更改实际上不会出现在 Facebook 中。
我以为我可以简单地实现另一个 UITextViewDelegate 方法:
- (BOOL)textViewShouldEndEditing:(UITextView *)textView
return NO;
UI 结果正是我想要的。但是,当我弹出 FacebookPostViewController 然后将另一个视图推送到 UINavigationController 时,这将导致 EXC_BAD_ACCESS 崩溃。那么错误是
*** -[UITextView isKindOfClass:]: message sent to deallocated instance 0x20c650
那么,有没有人知道如何解决我的问题,使 UITextView 不可编辑,但防止键盘消失?!?
【问题讨论】:
你让我坚持到最后。您使用 textViewShouldEndEditing: 提出的解决方案是我所建议的。您的崩溃与禁止界面的问题无关。如果您启动键盘并以某种方式释放它绑定的 UITextView,它当然会崩溃。我怀疑您需要在弹出 FacebookPostViewController 之前向 textView 发送一个 resignFirstResponder。 啊,谢谢你的建议!我不知道在释放 UITextView 时打开键盘会导致崩溃!但是,我尝试在 viewWillDisappear: 中调用 [self.textView resignFirstResponder],但这会导致再次调用 textViewShouldEndEditing:,这将防止键盘隐藏。但是由于您的提示,我找到了解决该问题的方法。我将其作为单独的答案发布。再次感谢! 好吧,即使你得到 textViewShouldEndEditing 你也只会在那个时候返回 YES - 你可以设置一个标志来知道你必须这样做。 【参考方案1】:好的,感谢上面David H 的评论,我找到了解决方案。但以下是最重要的见解:
当我从 UINavigationController 弹出 FacebookPostViewController 时,系统会自动要求 UITextView 放弃作为第一响应者.
您应该永远不要让 textViewShouldEndEditing: 始终返回 NO,因为这将始终阻止键盘隐藏,从而导致上述崩溃,一旦 UITextView 被释放。
解决方案是仅在我们仍在等待来自 Facebook 服务器的响应时才防止键盘消失。这是我添加的几行代码,它们正是这样做的:
@interface FacebookPostViewController ()
// ...
@property (nonatomic, assign, getter = isWaitingForFBResponse) BOOL waitingForFBResponse;
// ...
@end
@implementation FacebookPostViewController
// ...
@synthesize waitingForFBResponse = _waitingForFBResponse;
- (id)init;
self = [super init];
if (self)
// set default values
self.waitingForFBResponse = NO;
// ...
return self;
#pragma mark -
#pragma mark UITextViewDelegate methods
- (BOOL)textViewShouldEndEditing:(UITextView *)textView
if ([self isWaitingForFBResponse])
return NO;
else
return YES;
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
// Did user press 'return' (Send) key?
if([text isEqualToString:@"\n"])
// enter waiting state
self.waitingForFBResponse = YES;
// disable the user interface
[self disableUserInterface];
FacebookController *fbController = [FacebookController sharedFacebookController];
if ([fbController.facebook isSessionValid] == YES)
// Post to Facebook!
[self sendTextToFacebook];
else
// we need to login first
[self loginToFacebook];
// remember that user wants to post to Facebook
self.sendTextAfterFBLogin = YES;
// Don't allow textView to insert a LF into the text property
return NO;
// allow all other edits
return YES;
#pragma mark -
#pragma mark FBRequestDelegate methods
- (void)request:(FBRequest *)request didFailWithError:(NSError *)error;
// request failed, so display error status overlay.
[[FeedbackController sharedFeedbackController] displayStatusOverlayWithString:NSLocalizedString(@"StatusMessage_Failure", nil)];
// leave waiting state
self.waitingForFBResponse = NO;
// enable UI again
[self enableUserInterface];
- (void)request:(FBRequest *)request didLoad:(id)result;
// request succeeded, give user appropriate feedback.
[[FeedbackController sharedFeedbackController] displayStatusOverlayWithString:NSLocalizedString(@"StatusMessage_Sent", nil)];
// leave waiting state
self.waitingForFBResponse = NO;
// pop the view, as the user accomplished his goal.
[self.navigationController popViewControllerAnimated:YES];
@end
【讨论】:
以上是关于是否可以在不隐藏键盘的情况下使 UITextView 处于非活动状态(可编辑 = 否)?的主要内容,如果未能解决你的问题,请参考以下文章