1

我有课使用 HTTP Post 向 twitter 发布推​​文

这是一些代码 PostTweet.h

@interface PostTweet : NSObject
- (void)postMyTweet;
@end

PostTweet.m

- (void)postMyTweet 
{

    accountStore = [[ACAccountStore alloc] init];
    accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
    [accountStore requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error)
     {
         if (granted)
         {
             allAccounts = [accountStore accountsWithAccountType:accountType];

             if ([allAccounts count] > 0)
             {
                 userAccount = [allAccounts objectAtIndex:0];
                 userName = userAccount.username;
                 NSURL * reqURL = [NSURL URLWithString:ENDPOINT_MEDIA_UPLOAD];
                 NSDictionary * parameter = [NSDictionary dictionaryWithObject:tweetTitle forKey:@"status"];

                 SLRequest *twitterInfoRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter
                                                                    requestMethod:SLRequestMethodPOST
                                                                              URL:reqURL
                                                                       parameters:parameter];
                 [twitterInfoRequest addMultipartData:tweetImage withName:PARAM_MEDIA type:CONTENT_TYPE_MULTIPART_FORM_DATA filename:nil];

                 [twitterInfoRequest setAccount:userAccount];

                 [twitterInfoRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
                  {
                      //show status after done
                      long result = [urlResponse statusCode];



                      //Let us say that every thing is ok and I got 200 response 
                      if (result == 200)
                      {
                          NSLog(@"%ld",result);
                      }




                  }
                  ];
             }
         }
         else
         {
             NSLog(@"Not authorized");
         }
     }];

}

在我的viewcontroller.m

- (void) actuallySendTweet
{
    PostTweet * pt = [[PostTweet alloc] init];

    [pt postTweet];
    NSLog(@"Done");
}

问题是:调用 testMethod 后,如何等待 http 请求响应,我可以根据响应做任何事情。

现在发生的事情是,只要我调用 testMethod 立即NSLog执行并且不等待 http 响应。

4

2 回答 2

0

首先,如果你想协调两个不同的线程dispatch_semaphore_t可能比dispatch_group_t.

其次,更重要的是,您不应该采用异步方法,例如performRequestWithHandler,以同步方式从主队列调用它。你永远不应该阻塞主队列。

幸运的是performRequestWithHandler,给了我们一个handler块,我们可以在推文完成后使用它来执行操作。在您的评论中,您说您只是想在推文之后更新您的 HUD,所以您应该这样做performRequestWithHandler(将该 UI 更新发送回主队列,因为正如文档所说,“处理程序不能保证在任何特定线程”):

- (void)postMyTweet
{
    ACAccountStore *accountStore = [[ACAccountStore alloc] init];
    ACAccountType  *accountType  = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
    [accountStore requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error)
     {
         if (granted)
         {
             NSArray *allAccounts = [accountStore accountsWithAccountType:accountType];

             if ([allAccounts count] > 0)
             {
                 ACAccount    *userAccount = [allAccounts objectAtIndex:0];
                 NSURL        *reqURL      = [NSURL URLWithString:ENDPOINT_MEDIA_UPLOAD];
                 NSDictionary *parameter   = [NSDictionary dictionaryWithObject:tweetTitle forKey:@"status"];

                 SLRequest *twitterRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter
                                                                requestMethod:SLRequestMethodPOST
                                                                          URL:reqURL
                                                                   parameters:parameter];

                 [twitterRequest addMultipartData:tweetImage withName:PARAM_MEDIA type:CONTENT_TYPE_MULTIPART_FORM_DATA filename:nil];
                 [twitterRequest setAccount:userAccount];
                 [twitterRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
                  {
                      if (error)
                          NSLog(@"tweet fail; error = %@", error);
                      else
                      {
                          long result = [urlResponse statusCode];

                          if (result == 200)
                              NSLog(@"%ld",result);
                          else
                              NSLog(@"Unexpected response: %@", [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]]);
                      }

                      // Dispatch UI updates back to main queue

                      dispatch_async(dispatch_get_main_queue(), ^{
                          // do your MBProgressHUD stuff here
                      });
                  }];
             }
         }
         else
         {
             NSLog(@"Not authorized");
         }
     }];
}

您还问“如何将 HTTP 响应结果传递给视图控制器?” 显然performRequestWithHandler,您在有 HTTP 响应(和响应数据)的地方执行所有这些操作。


如果您想postTweet同步操作,那么最佳实践将要求您不要从主队列提交它(因为,冒着听起来像破记录的风险,您永远不想阻塞主队列)。但是你可以actuallySendTweet从后台队列中发送这条推文,例如:

- (void) actuallySendTweet
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        PostTweet * pt = [[PostTweet alloc] init];

        [pt postTweetSynchronously];

        NSLog(@"Done");

        dispatch_async(dispatch_get_main_queue(), ^{
            // Now do any UI updates you want here.

            // For example, do your MBProgressHUD update here.
        });
    });
}

- (void)postTweetSynchronously
{
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

    ACAccountStore *accountStore = [[ACAccountStore alloc] init];
    ACAccountType  *accountType  = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
    [accountStore requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error)
     {
         if (granted)
         {
             NSArray *allAccounts = [accountStore accountsWithAccountType:accountType];

             if ([allAccounts count] > 0)
             {
                 ACAccount    *userAccount = [allAccounts objectAtIndex:0];
                 NSURL        *reqURL      = [NSURL URLWithString:ENDPOINT_MEDIA_UPLOAD];
                 NSDictionary *parameter   = [NSDictionary dictionaryWithObject:tweetTitle forKey:@"status"];

                 SLRequest *twitterRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter
                                                                requestMethod:SLRequestMethodPOST
                                                                          URL:reqURL
                                                                   parameters:parameter];

                 [twitterRequest addMultipartData:tweetImage withName:PARAM_MEDIA type:CONTENT_TYPE_MULTIPART_FORM_DATA filename:nil];
                 [twitterRequest setAccount:userAccount];

                 [twitterRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
                  {
                      // do whatever you want here, perhaps updating some class properties

                      // now that we're done, signal the semaphore
                      dispatch_semaphore_signal(semaphore);
                  }];
             }
         }
         else
         {
             NSLog(@"Not authorized");
             dispatch_semaphore_signal(semaphore); // make sure to signal here, too
         }
     }];

     dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
于 2013-06-04T13:17:02.047 回答
-1

在这里,您正在使用完成块。线程不等待块的执行。因此,如果您希望块的执行应该在完成方法执行之前完成并处理数据,您可以使用,

dispatch_group_t

我正在为此编辑你的方法,

- (void)postMyTweet 
{

    accountStore = [[ACAccountStore alloc] init];
    accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];

    dispatch_group_t group = dispatch_group_create();

    dispatch_group_enter(group);

    [accountStore requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error)
     {
         if (granted)
         {
             allAccounts = [accountStore accountsWithAccountType:accountType];

             if ([allAccounts count] > 0)
             {
                 userAccount = [allAccounts objectAtIndex:0];
                 userName = userAccount.username;
                 NSURL * reqURL = [NSURL URLWithString:ENDPOINT_MEDIA_UPLOAD];
                 NSDictionary * parameter = [NSDictionary dictionaryWithObject:tweetTitle forKey:@"status"];

                 SLRequest *twitterInfoRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter
                                                                    requestMethod:SLRequestMethodPOST
                                                                              URL:reqURL
                                                                       parameters:parameter];
                 [twitterInfoRequest addMultipartData:tweetImage withName:PARAM_MEDIA type:CONTENT_TYPE_MULTIPART_FORM_DATA filename:nil];

                 [twitterInfoRequest setAccount:userAccount];

                 [twitterInfoRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
                  {
                      //show status after done
                      long result = [urlResponse statusCode];



                      //Let us say that every thing is ok and I got 200 response 
                      if (result == 200)
                      {
                          NSLog(@"%ld",result);
                      }


                      dispatch_group_leave(group);
                  }
                  ];
             }
         }
         else
         {
             NSLog(@"Not authorized");
             dispatch_group_leave(group);
         }
     }];

     dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    dispatch_release(group);

}

现在从这里你可以得到想法。

于 2013-06-03T05:57:23.647 回答