0

我在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 不可编辑,但防止键盘消失?!?

4

1 回答 1

0

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

  1. 当我从UINavigationController弹出我的FacebookPostViewController时,系统会自动要求UITextView辞去第一响应者的职务。

  2. 永远不应该让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
于 2012-08-14T12:01:35.650 回答