MBProgressHUD + Facebook SKD: Nested blocks - ios

I'm trying to add a Facebook login to my app with the Facebook SDK for iOS.
Because the request to Facebook's servers may take some time, I thought to use MBProgressHUD.
The problem is that both MBProgressHUD and FBRequest use blocks, so I'm expecting some strange behavior.
This is the code i used:
MBProgressHUD *HUD = [[MBProgressHUD alloc] initWithView:self.view];
[self.view addSubview:HUD];
HUD.delegate = self;
HUD.labelText = #"Loading";
HUD.minSize = CGSizeMake(135.f, 135.f);
[HUD showAnimated:YES whileExecutingBlock:^{
[FBSession openActiveSessionWithReadPermissions:#[#"email"] allowLoginUI:YES completionHandler:^(FBSession *session, FBSessionState state, NSError *error) {
if (error) {
HUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"error"]];
HUD.mode = MBProgressHUDModeCustomView;
HUD.detailsLabelText = error.localizedFailureReason;
HUD.labelText = #"Error";
}
if (state == FBSessionStateClosedLoginFailed) {
[FBSession.activeSession closeAndClearTokenInformation];
}
if (FBSession.activeSession.isOpen) {
[[FBRequest requestForMe] startWithCompletionHandler:^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) {
if (!error) {
//Save User's Data
HUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"37x-Checkmark.png"]];
HUD.mode = MBProgressHUDModeCustomView;
HUD.labelText = #"Logged in";
} else {
HUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"error"]];
HUD.mode = MBProgressHUDModeCustomView;
HUD.detailsLabelText = #"An error occurred, please retry later";
HUD.labelText = #"Error";
}
}];
}
}];
sleep(2);
} completionBlock:^{
//Return to previous page
}];
The problem is that when I push the button related to this method, I see the progress HUD for less than a second, then I'm brought back to the previous page.
What I'd like to see is the HUD displayed during all the process.
Can someone tell me how to do it?
Thanks

The problem is that showAnimated:whileExecutingBlock: closes the HUD right after the block completes. The facebook authentication method executes code in the background and returns immediately. Instead, try just showing the HUD, and hiding it in the Facebook completion blocks.
-(void)yourMethodThatLogsIntoFacebook {
MBProgressHUD *HUD = [[MBProgressHUD alloc] initWithView:self.view];
[self.view addSubview:HUD];
HUD.delegate = self;
HUD.labelText = #"Loading";
HUD.minSize = CGSizeMake(135.f, 135.f);
[HUD show:YES];
[FBSession :#[#"email"] allowLoginUI:YES completionHandler:^(FBSession *session, FBSessionState state, NSError *error) {
if (error) {
[self updateHud:HUD withImage:#"error" text:#"Error" detailText:error.localizedFailureReason];
}
if (state == FBSessionStateClosedLoginFailed) {
[FBSession.activeSession closeAndClearTokenInformation];
}
if (FBSession.activeSession.isOpen) {
[[FBRequest requestForMe] startWithCompletionHandler:^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) {
if (!error) {
//Save User's Data
[self updateHud:HUD withImage:#"37x-Checkmark.png" text:#"Logged in" detailText:nil];
} else {
[self updateHud:HUD withImage:#"error" text:#"Error" detailText:#"An error occurred, please retry later"];
}
}];
}
}];
}
-(void)updateHud:(MBProgressHUD *)hud withImage:(NSString *)imageName text:(NSString *)text detailText:(NSString *)detailText {
hud.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:imageName]];
hud.mode = MBProgressHUDModeCustomView;
hud.labelText = text;
hud.detailText = detailText;
[hud hide:YES afterDelay:2.];
}

Related

Post multiple images using SLComposeViewController on Facebook/ Twitter?

I am an iOS developer and I am currently using SLComposeViewController to share a post on Facebook/Twitter. My issue is that I have to post multiple images in a single post.
I have done this as follows:
SLComposeViewController* mySLComposerSheet = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeTwitter];
[mySLComposerSheet setInitialText:textTobeShared];
mySLComposerSheet addURL:[NSURL URLWithString:#"http://click-labs.com/"]];
for(int count=0;count<imageArray.count;count++)
if([mySLComposerSheet addImage:[UIImage imageWithData:[imageArray objectAtIndex:count]]])
In the above code, imageArray is the array of images that I want to post.
When I am doing this on Facebook, all the images are posted as a separate post.
While in case of Twitter, addImage method returns true only for the first images while in case of other images it returns false. So only one image is posted.
So I want to know how to achieve my goal and is it possible to post multiple images in a single tweet.
I think you need to create an album first.
Here's a link to the facebook album API documentation.
- (void)shareToFacebook {
if (FBSession.activeSession.isOpen) {
NSLog(#"SESSION IS OPEN");
[self createFacebookAlbum];
} else {
NSLog(#"SESSION IS NOT OPEN");
NSArray* permissions = [NSArray arrayWithObject:#"email"];
[FBSession openActiveSessionWithReadPermissions:permissions allowLoginUI:YES completionHandler:^(FBSession *session, FBSessionState state, NSError *error) {
[self sessionStateChanged:session state:state error:error];
if (error) {
/* handle failure */
NSLog(#"error:%#, %#", error, [error localizedDescription]);
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"There was a problem with your Facebook permissions." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
}
else if (state == FBSessionStateClosed || state == FBSessionStateClosedLoginFailed ) {
[FBSession.activeSession closeAndClearTokenInformation];
}
else if (state == FBSessionStateOpenTokenExtended || state == FBSessionStateOpen) {
if(!self.presentedFacebookSheet) {
[self performSelector:#selector(reauthorizeAndContinuePostToFacebook) withObject:nil afterDelay:0.5];
self.presentedFacebookSheet = YES;
}
}
}];
}
}
- (void)reauthorizeAndContinuePostToFacebook {
NSArray *permissions = [NSArray arrayWithObjects:#"publish_actions", nil];
[[FBSession activeSession] requestNewPublishPermissions:permissions defaultAudience:FBSessionDefaultAudienceFriends completionHandler:^(FBSession *session, NSError *error) {
[self shareToFacebook];
}];
}
- (void)createFacebookAlbum {
NSMutableDictionary* parameters = [NSMutableDictionary dictionary];
[parameters setObject:#"Test name" forKey:#"name"];
[parameters setObject:#"Test message" forKey:#"message"];
FBRequest* request = [FBRequest requestWithGraphPath:#"me/albums" parameters:parameters HTTPMethod:#"POST"];
NSLog(#"creating facebook album");
FBRequestConnection *connection = [[FBRequestConnection alloc] init];
[connection addRequest:request
completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
if (!error) {
NSString* albumId = [result objectForKey:#"id"];
NSLog(#"OK %#", albumId);
}
else {
NSLog(#"Error: %#",error.userInfo);
}
}];
[connection start];
}
- (void)sessionStateChanged:(FBSession *)session state:(FBSessionState) state error:(NSError *)error {
switch (state) {
case FBSessionStateOpen:
{
[[FBRequest requestForMe] startWithCompletionHandler:
^(FBRequestConnection *connection,
NSDictionary<FBGraphUser> *user,
NSError *error) {
if (error) {
//error
}
else {
NSLog(#"User session found");
}
}];
}
break;
case FBSessionStateClosed:
case FBSessionStateClosedLoginFailed:
[FBSession.activeSession closeAndClearTokenInformation];
break;
default:
break;
}
}

Block UITableView not scrolling , when get Facebook Friend List - ios

I have implement a script to get list friends in my facebook include image, username....
But when it load to viewcontroller ( uitableview ) list friends has return but the tableview be block scrolling, please help
'- (void)getFriendsListWithCompleteBlock:(void (^)(NSArray *, NSString *))completed{
if (!FBSession.activeSession.isOpen)
{
NSLog(#"permissions::%#",FBSession.activeSession.permissions);
// if the session is closed, then we open it here, and establish a handler for state changes
[FBSession openActiveSessionWithReadPermissions:#[#"basic_info", #"user_friends"]
allowLoginUI:YES
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error) {
if (error)
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:error.localizedDescription
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
}
else if (session.isOpen)
{
[self showWithStatus:#""];
FBRequest *friendRequest = [FBRequest requestForGraphPath:#"me/friends?fields=name,picture,gender"];
[friendRequest startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
NSArray *data = [result objectForKey:#"data"];
NSMutableArray *friendsList = [[NSMutableArray alloc] init];
for (FBGraphObject<FBGraphUser> *friend in data)
{
//NSLog(#"friend:%#", friend);
NSDictionary *picture = [friend objectForKey:#"picture"];
NSDictionary *pictureData = [picture objectForKey:#"data"];
//NSLog(#"picture:%#", picture);
FBData *fb = [[FBData alloc]
initWithData:(NSString*)[friend objectForKey:#"name"]
userID:(NSInteger)[[friend objectForKey:#"id"] integerValue]
gender:(NSString*)[friend objectForKey:#"gender"]
photoURL:(NSString*)[pictureData objectForKey:#"url"]
photo:(UIImage*)nil
isPhotoDownloaded:(BOOL)NO];
[friendsList addObject:fb];
}
NSString *message;
if (friendsList.count <1) {
message = #"Not Founds";
}
[self dismissStatus];
dispatch_async(dispatch_get_main_queue(), ^{
if (completed) {
completed(friendsList,message);
}
});
}];
}
}];
}
}
'

Hyper link in iOS Facebook

I need to share the link to Facebook. when user press that link that should take user to another page.
I tried the following code..but it only just share string..it doest not act like hyperlink..
-(void)fbShare
{
[hud show:YES];
NSString *title=[NSString stringWithFormat:#"www.google.com"];
MAAppDelegate *appdelegate = (MAAppDelegate *)[[UIApplication sharedApplication] delegate] ;
if (!appdelegate.session) {
appdelegate.session = [[FBSession alloc]initWithPermissions:[NSArray arrayWithObjects:#"publish_stream",nil]];
}
if (![appdelegate.session isOpen]) {
[appdelegate.session openWithCompletionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
if (!error) {
[self Share:title];
}else {
NSLog(#"facebook errror %#",error.description);
[hud hide:YES];
}
}];
} else {
[self Share:title];
}
}
-(void)Share:(NSString *)text
{
MAAppDelegate *appdelegate = (MAAppDelegate *)[[UIApplication sharedApplication] delegate];
UIImage *image = [UIImage imageNamed:#"bath3.png"];
[FBSession setActiveSession:appdelegate.session];
NSData *dataImage=UIImageJPEGRepresentation(image,1.0);
NSMutableDictionary *parameters = [NSMutableDictionary dictionaryWithObjectsAndKeys:text, #"name", dataImage, #"picture", #"image/png", #"content_type", nil];
FBRequest *request=[FBRequest requestWithGraphPath:#"me/photos" parameters:parameters HTTPMethod:#"POST"];
[request startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
if(!error) {
NSLog(#"Success");
[hud hide:YES];
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:#"Audalize POC" message:#"Shared Successfully" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
} else {
[hud hide:YES];
NSLog(#"failed %#",error.localizedDescription);
}
}];
}
Read this : https://developers.facebook.com/docs/ios/share/
You need to use " link" key for sharing links to facebook.
Ex :
[NSMutableDictionary dictionaryWithObjectsAndKeys:text,#"link", // < ----
dataImage,#"picture",
#"image/png",#"content_type"
,nil];

FBSession: an attempt was made reauthorize permissions on an unopened session in ios

Hi I am using facebook SDK 3.8 in my project. and using HelloFaceBookSample Code in my app but in my app i have no login button of facebook. I have implemented login flow of facebook and after login i have post on facebook. Now Post Status working fine but when i post image on facebook it give me error of
an attempt was made reauthorize permissions on an unopened session in ios
Code :
-(void) clickButtonFacebookUsingSDK
{
if (!appdelegate.session.isOpen)
{
appdelegate.session = [[FBSession alloc] init];
[appdelegate.session openWithCompletionHandler:^(FBSession *session,
FBSessionState status,
NSError *error) {
if(appdelegate.session.isOpen)
{
NSLog(#"calling postdata when session is not open******");
[self postData];
}
}];
}
else
{
NSLog(#"calling postdata when session is open******");
[self postData];
}
}
-(void) postData
{
[self showingActivityIndicator];
UIImage *img = [UIImage imageNamed:#"abc.jpg"];
[self performPublishAction:^{
FBRequestConnection *connection = [[FBRequestConnection alloc] init];
connection.errorBehavior = FBRequestConnectionErrorBehaviorReconnectSession
| FBRequestConnectionErrorBehaviorAlertUser
| FBRequestConnectionErrorBehaviorRetry;
FBRequest *req = [FBRequest requestForUploadPhoto:img];
[req.parameters addEntriesFromDictionary:[NSMutableDictionary dictionaryWithObjectsAndKeys:message3, #"message", nil]];
[connection addRequest:req
completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
// [self showAlert:#"Photo Post" result:result error:error];
[self showAlert:#"Photo Post" result:result resulterror:error];
if (FBSession.activeSession.isOpen) {
}
}];
[connection start];
}];
}
- (void) performPublishAction:(void (^)(void)) action {
// we defer request for permission to post to the moment of post, then we check for the permission
if ([FBSession.activeSession.permissions indexOfObject:#"publish_actions"] == NSNotFound)
{
// if we don't already have the permission, then we request it now
[FBSession.activeSession requestNewPublishPermissions:#[#"publish_actions"]
defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:^(FBSession *session, NSError *error)
{
if (!error) {
action();
} else if (error.fberrorCategory != FBErrorCategoryUserCancelled){
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Permission denied"
message:#"Unable to get permission to post"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
}
}];
} else {
action();
}
}
// UIAlertView helper for post buttons
- (void)showAlert:(NSString *)message result:(id)result resulterror:(NSError *)error
{
NSString *alertMsg;
NSString *alertTitle;
if (error)
{
alertTitle = #"Error";
// Since we use FBRequestConnectionErrorBehaviorAlertUser,
// we do not need to surface our own alert view if there is an
// an fberrorUserMessage unless the session is closed.
if (FBSession.activeSession.isOpen) {
alertTitle = #"Error";
} else {
// Otherwise, use a general "connection problem" message.
alertMsg = #"Operation failed due to a connection problem, retry later.";
}
}
else
{
NSDictionary *resultDict = (NSDictionary *)result;
alertMsg = [NSString stringWithFormat:#"Successfully posted '%#'.", message];
NSString *postId = [resultDict valueForKey:#"id"];
if (!postId) {
postId = [resultDict valueForKey:#"postId"];
}
if (postId) {
alertMsg = [NSString stringWithFormat:#"%#\nPost ID: %#", alertMsg, postId];
}
alertTitle = #"Success";
}
if (alertTitle) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:alertTitle
message:alertMsg
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
[self dismissActivityIndicator];
}
}
it gives me error in performPublishAction method.
can anyone tell me what is the problem . i have a lot of search and also found many solution but no one work. Please help. Thanks in advance.
I think that you have to set to FBSession what is its active session :
FBSession *session = [[FBSession alloc] init];
[FBSession setActiveSession:session];

How not to ask for publish permission everytime?

I did this in facebook
[self vSuspendAndHaltThisThreadTillUnsuspendedWhileDoing:^{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self.ACAstore requestAccessToAccountsWithType:self.ACAccounts options:[self dicPostOptions] completion:^(BOOL granted, NSError *error) {
self.bPermissionToAccessStoreGranted=granted;
[self vContinue];
}];
}];
}];
Basically I am asking for publish permission. What I want to do is to check whether such publish permission has been granted or not before asking again.
How to do so?
To check permissions available:
if(![postRequest.session.permissions containsObject:#"publish_actions"])
You can make an FBRequest with the open graph API with me/permissions. It will return you a response with a dictionary where the key are the permissions.
FBRequest *req = [FBRequest requestWithGraphPath:#"me/permissions" parameters:Nil HTTPMethod:#"GET"];
[req startWithCompletionHandler: ^(FBRequestConnection *connection,
NSDictionary* result,
NSError *error) {
BOOL canPublish = FALSE;
if (!error)
{
FBGraphObject *data = [result objectForKey:#"data"];
for(NSDictionary<FBGraphObject> *aKey in data)
{
canPublish = [[aKey objectForKey:#"publish_stream"] boolValue];
}
}
else
{
NSLog(#"%#", error);
}
NSLog(#"%#", canPublish ? #"I have publish perms" : #"I don't have publish perms");
}];
Try this -
First of all implement all the facebook sdk delegate methods in your app delegate.
- (IBAction)loginWithFacebookButtonTapped:(id)sender
{
IntubeAppDelegate *delegat = (IntubeAppDelegate*)[[UIApplication sharedApplication] delegate];
[delegat doLoginAndSwitch];
}
Now, in your appDelegate -
-(void) doLoginAndSwitch
{
[self openSessionWithAllowLoginUI:YES];
}
- (BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI
{
NSArray *permissions = [NSArray arrayWithObjects:#"email", nil];
return [FBSession openActiveSessionWithPublishPermissions:permissions
defaultAudience:FBSessionDefaultAudienceFriends
allowLoginUI:YES
completionHandler:^(FBSession *session, FBSessionState state, NSError *error) {
[self sessionStateChanged:session
state:state
error:error];
}];
}
-(BOOL)openSessionWithAllowPublishStreamPermission:(BOOL)allowLoginUI
{
NSArray *permissions = [NSArray arrayWithObjects:#"publish_actions",#"publish_stream", nil];
[[FBSession activeSession] requestNewPublishPermissions:permissions defaultAudience:FBSessionDefaultAudienceEveryone completionHandler:^(FBSession *session, NSError *error){
}];
return YES;
}
- (void)sessionStateChanged:(FBSession *)session
state:(FBSessionState)state
error:(NSError *)error
{
switch (state) {
case FBSessionStateOpen:
if(!error)
{
// NSLog(#"FBSessionStateOpen :- logged in");
[self openSessionWithAllowPublishStreamPermission:YES];
// Your code
}
}
}
I hope you would get what you desire now. :)

Resources