是否可以在不隐藏键盘的情况下使UITextView无效(editable = NO)?

时间:2012-08-13 19:06:46

标签: ios facebook user-interface uitextview uitextviewdelegate

我在 UIViewController 的子类中使用 UITextView ,我将其命名为 FacebookPostViewController 。因此,文本视图的目的是允许用户查看准备好的帖子的内容,可能对其进行更改,然后决定文本视图中的文本是否应该发布到Facebook。

我已将UITextView的 returnKeyType 属性设置为 UIReturnKeySend ,因为我想用它来实际发布到Facebook。可以通过导航栏中的后退按钮取消。

所以 FacebookPostViewController 是UITextView的委托,并且在 textView:shouldChangeTextInRange:replacementText:委托方法中,我检查换行符插入,然后调用我的< em> 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不可编辑,但防止键盘消失?!

1 个答案:

答案 0 :(得分:0)

好的,感谢上面David H的评论,我找到了一个解决方案。但这里有最重要的见解:

  1. 当我从 UINavigationController 中弹出 FacebookPostViewController 时,系统会自动询问 UITextView 以便辞职成为第一个响应者

  2. 你应该从不 textViewShouldEndEditing:总是返回NO,因为这总是会阻止键盘隐藏,这会导致上述崩溃,一旦 UITextView 被解除分配。

  3. 解决方法是防止键盘消失,以防我们仍在等待来自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