我上课时使用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响应。
答案 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);
}
现在你可以从中获得想法。