I have class that post a tweet to twitter using HTTP Post
here is a bit of code 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");
}
}];
}
In my viewcontroller.m
- (void) actuallySendTweet
{
PostTweet * pt = [[PostTweet alloc] init];
[pt postTweet];
NSLog(@"Done");
}
The Question is: after calling The testMethod, How to wait for the http request response and I can do anything based on the response.
What happens now is that as soon as I call the testMethod the NSLog
perform right away and does not wait for the http response.
First, if you wanted to coordinate two different threads dispatch_semaphore_t
might be more appropriate than dispatch_group_t
.
Second, and more importantly, you should not take an asynchronous method such as performRequestWithHandler
, invoke it from the main queue in a synchronous manner. You never should be blocking the main queue.
Fortunately performRequestWithHandler
gives us a handler
block which we can use to perform actions after the tweet is done. In your comments, you say you simply want to update your HUD after the tweet, so you should do that performRequestWithHandler
(dispatching that UI update back to the main queue, because, as the documentation says, "handler is not guaranteed to be called on any particular thread"):
- (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");
}
}];
}
You also asked "How can I pass the HTTP response result to the viewcontroller?" You obviously do all of this in performRequestWithHandler
, where you have the HTTP response (and the response data).
If you want postTweet
to operate synchronously, then best practices would dictate that you don't submit it from the main queue (because, at the risk of sounding like a broken record, you never want to block the main queue). But you could have actuallySendTweet
dispatch this tweet from a background queue, eg:
- (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);
}
As here you are using completion block. The thread does not wait for the execution of block. So it you want that execution of block should complete and precess the data before finishing the execution of method, you can use,
dispatch_group_t
I am editing your method for that,
- (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);
}
Now from this you can get idea.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.