如何等待然后执行基于HTTP请求响应iOS的操作

时间:2013-06-03 05:45:38

标签: iphone ios objective-c http

我上课时使用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响应。

2 个答案:

答案 0 :(得分:0)

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

其次,更重要的是,您不应采用performRequestWithHandler之类的异步方法,以同步方式从主队列中调用它。你从不应该阻止主队列。

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

- (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响应结果传递给viewcontroller?”你显然在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);
}

答案 1 :(得分:-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);

}

现在你可以从中获得想法。