Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>If you do not care about receiving state changes from FBSessionStateHandler like I did then the the code below should allow you to login to Facebook and provide you with a completion block that is not retained.</p> <p>The completion block that is passed into the method will always get used when any state change occurs and then immediately nil'd out so that if another state change occurs it is ignored.</p> <pre><code>typedef void(^FacebookLoginCompletionBlock)(id&lt;FBGraphUser&gt; user); - (void)loginToFacebookFromWithCompletionBlock:(FacebookLoginCompletionBlock)completionBlock { // If the user is not logged into Facebook attempt to open a session with "publish_actions" permissions. if([[FBSession activeSession] isOpen] == NO) { // Copy the completion block to a local variable so it can be nil'd out after it is used to prevent retain loops. __block FacebookLoginCompletionBlock copiedCompletionBlock = completionBlock; [FBSession openActiveSessionWithPublishPermissions:@[ @"publish_actions" ] defaultAudience:FBSessionDefaultAudienceFriends allowLoginUI:YES completionHandler:^(FBSession *session, FBSessionState status, NSError *error) { // Only attempt to run any of this code if there is a completion block to call back to. If completion block is nil than it has already been used and this is a state change that we do not care about. if(copiedCompletionBlock != nil) { // Because this method is only concerned with the user logging into Facebook just worry about the open state occuring with no errors. if(status == FBSessionStateOpen &amp;&amp; error == nil) { // If the user successfully logged into Facebook download their basic profile information so the app can save the information to display to the user what account they are logged in under. [FBRequestConnection startForMeWithCompletionHandler:^(FBRequestConnection *connection, id&lt;FBGraphUser&gt; user, NSError *error) { if(copiedCompletionBlock != nil) copiedCompletionBlock(user); // nil out the copied completion block so it is not retained and called everytime the active FBSession's state changes. copiedCompletionBlock = nil; }]; } // Because this method is only concerned with the user logging into Facebook if any other state is triggered call the completion block indicating that there was a failure. else { if(copiedCompletionBlock != nil) copiedCompletionBlock(nil); // nil out the copied completion block so it is not retained and called everytime the active FBSession's state changes. copiedCompletionBlock = nil; } } // This block will exist the lifespan of the application because for some bizarre reason Facebook retains the completion handler for their open active session methods. Throw in some code that will display an error to the user if any session state changes occur that Facebook thinks the user should be aware of. Your code should be always checking if a active Facebook session exists before taking any action so not being aware of these changes should not be any issue. Worst case scenario you can listen for FBSessionDidSetActiveSessionNotification, FBSessionDidUnsetActiveSessionNotification, FBSessionDidBecomeOpenActiveSessionNotification or FBSessionDidBecomeClosedActiveSessionNotification notifications. if ([error fberrorShouldNotifyUser] == YES) { NSString *alertTitle = @"Error logging into Facebook"; NSString *alertMessage = [error fberrorUserMessage]; if ([alertMessage length] == 0) alertMessage = @"Please try again later."; UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:alertTitle message:alertMessage delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alertView show]; } }]; } // If the user is already logged into Facebook immediately call the completion block with the user object that should have been saved when the user previously logged in. else { if(completionBlock != nil) completionBlock([self facebookUser]); } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload