0

FacebookPostViewControllerという名前のUIViewControllerのサブクラスでUITextViewを使用します。したがって、テキスト ビューの目的は、ユーザーが準備された投稿の内容を確認し、場合によっては変更を加え、テキスト ビューのテキストを Facebook に投稿するかどうかを決定できるようにすることです。

UITextView のreturnKeyTypeプロパティをUIReturnKeySendに設定しました。実際に Facebook に投稿するために使用したいからです。NavBar の戻るボタンでキャンセルできます。

したがって、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];
}

ご覧のとおり、 FBRequestDelegateとしてselfを指定しているので、実装も行います。

- (void)request:(FBRequest *)request didFailWithError:(NSError *)error;
- (void)request:(FBRequest *)request didLoad:(id)result;

投稿が成功したかどうかをユーザーにフィードバックします。

ただし、Facebook サーバーが応答するまでに時間がかかることがわかったので、2 つのデリゲート メソッドのいずれかが呼び出されるまで、完全な 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. UITextViewの割り当てが解除されるとすぐに、キーボードが非表示になり、上記のクラッシュが発生するため、 textViewShouldEndEditing:が常に NO を返すようにしないください。

解決策は、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 に答える