Facebook Developers
DocsToolsSupportNewsApps
Log In
  • Social Plugins
  • Facebook Login
  • Open Graph
  • Facebook APIs
  • Games
  • Media
  • Payments
  • App Center
  • Promote Your App
  • iOS
  • Android
  • Web
  • Technology Partners
  • Topics
    • Facebook SDK for iOS
  • Getting Started
    • Getting Started with the Facebook SDK for iOS
    • Build, Distribute and Promote
  • iOS SDK Tutorial
    • Facebook iOS SDK Tutorial
    • 1 - Authenticate Using Facebook Login
    • 2 - Personalize
    • 3 - Show Friends
    • 4 - Show Nearby Places
    • 5 - Publish Open Graph Story
  • Games Tutorial
    • iOS Games Tutorial
    • 1 - Authenticate
    • 2 - Personalize
    • 3 - Invites and Requests
    • 4 - Bragging and News Feed
    • 5 - Publish Open Graph Story
  • Upgrading SDKs Tutorials
    • Upgrading from 3.2 to 3.5
    • Upgrading from 3.1 to 3.2
    • Upgrading from 3.0 to 3.1
    • Upgrading from 2.0 to 3.1

5 - Publish Open Graph Story

Documentation › Facebook iOS SDK Tutorial › 5 - Publish Open Graph Story

In this tutorial, you'll bring everything together and publish an Open Graph story. The previous steps let the user specify where they are and who they're with. Now, we'll implement a flow that lets the user select a meal and upload a photo to share what they're doing. Once they enter this information, they can publish a rich story that looks like this:

The FBRequest class has a helper method called requestForUploadPhoto:, which lets you quickly set up a request to post a photo to the app's album. When you provide a UIImage for the photo, you'll get an FBRequest object back. Then, you can initialize and start the connection to upload the photo.

The FBRequest class also has a requestForGraphPath: method that is used to make a Graph API call to get information for any Facebook object by passing in an NSString representing the path to the object. For example, you can pass me to retrieve basic user information corresponding to the session. In this tutorial, you'll pass in an object ID representing the uploaded photo. You'll then use the returned data to help publish the Open Graph action.

The action you'll publish will include information about the meal and if available, optional information representing the selected friends, place and photo. You'll use the method startForPostWithGraphPath:graphObject:completionHandler: in the FBRequestConnection class to publish the action. The graphPath you pass will correspond to the me/<YOUR_NAMESPACE>:eat Open Graph action. The graphObject parameter will be a protocol object based on the FBGraphObject protocol and will represent the publish action parameters.

This tutorial walks through the following:

  • Step 1: Configure Open Graph in the App Dashboard
  • Step 2: Set Up Your Backend Server
  • Step 3: Publish a Test Action
  • Step 4: Add the Meal Selection Flow
  • Step 5: Add the Photo Selection Flow
  • Step 6: Add the Publish Action Button
  • Step 7: Implement the Publish Action
  • Next Steps
  • Related Samples

Note: Before you start this tutorial, make sure you've run through the Show Nearby Places Tutorial.


Step 1: Configure Open Graph in the App Dashboard

In this step, you'll define the Open Graph action, object and aggregation in the App Dashboard.

First, set up an app namespace. It has to be unique; you'll use it to define your Open Graph actions and objects.

If you don't have a backend server, you can set one up through one of our partners. We'll discuss this further in the next step.

Once you have an app namespace, define an ''eat'' action and a corresponding ''meal'' object. You can define a simple aggregation on the ''eat'' action that will display a list the meals eaten recently on the user's timeline. See the Open Graph Tutorial for more details on setting up your action, object and aggregation.

When you're done with the flow your Open Graph dashboard should look like this:

Next, set up a backend server to host your objects.


Step 2: Set Up Your Backend Server

Open Graph objects need to exist as webpages on a server that Facebook can access. These pages have special markup, called Open Graph tags, that Facebook servers scrape to properly identify the data and connect it to the user. For example, you could have a ''pizza'' webpage that represents a ''pizza'' type of meal. When the user publishes a story with your app, this will connect an ''eat'' action to the ''pizza'' object.

In this tutorial, you won't set up static pages to represent each meal (ex: pizza or hot dogs). Instead, you'll create a dynamic endpoint that creates the proper object Open Graph markup. Here's a sample PHP endpoint:

&lt;?php
function curPageURL() {
 $pageURL = 'http://';
 if ($_SERVER["SERVER_PORT"] != "80") {
  $pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
 } else {
  $pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
 }
 return $pageURL;
}
?>

&lt;html>
  &lt;head prefix="og: http://ogp.me/ns# product: http://ogp.me/ns/product#">
    &lt;meta property="fb:app_id" content="&lt;?php echo strip_tags($_REQUEST['fb:app_id']);?>">
      &lt;meta property="og:url" content="&lt;?php echo strip_tags(curPageURL());?>">
      &lt;meta property="og:type" content="&lt;?php echo strip_tags($_REQUEST['og:type']);?>">
      &lt;meta property="og:title" content="&lt;?php echo strip_tags($_REQUEST['og:title']);?>">
      &lt;meta property="og:image" content="&lt;?php echo strip_tags($_REQUEST['og:image']);?>">
      &lt;meta property="og:description" content="&lt;?php echo strip_tags($_REQUEST['og:description']);?>">
      &lt;title>Product Name&lt;/title>
  &lt;/head>
    &lt;body>
      &lt;?php echo strip_tags($_REQUEST['body']);?>
    &lt;/body>
&lt;/html>

Upload this sample PHP file or similar code to your backend server. If you don't have a backend server, try one of the services we partner with, like Heroku. You can initiate the setup right from the App Dashboard on the app's basic settings page.

Once you've uploaded the dynamic object creation code, test a sample object using the Object Debugger. Enter a URL into the debugger, for example:

https://fbsdkog.herokuapp.com/repeater.php?fb:app_id=233936543368280
&og:type=fb_sample_scrumps:meal
&og:title=Pizza
&og:description="Pizza"
&og:image=https%3A%2F%2Fs-static.ak.fbcdn.net%2Fimages%2Fdevsite%2Fattachment_blank.png
&body=Pizza

Fix any errors you find before moving to the next step.


Step 3: Publish a Test Action

Now that you've configured your Open Graph information and set up your objects, try publishing an action outside of your iOS app with the Graph API Explorer. Go to the Graph API Explorer and select your app from the ''Application'' list. Then, change the action type from the default ''GET'' to ''POST''. Enter me/<YOUR_APP_NAMESPACE>:eat in the Graph API endpoint field and add the following POST data:

  • meal = <OBJECT_URL>
  • image[0][url] = <LINK_TO_AN_IMAGE> e.g. http://www.sugarmedia.com/nyccookbook/images/pizza.jpg
  • tags = <FRIEND_USER_ID>
  • place = <PLACE_ID> e.g. 111615355559307

Once you enter the additional fields, your form should look like this:

Submit your test action. You should see a result ID similar to:

{
  "id": "4413537462971"
}

Now, login to Facebook and go to your Activity Log to verify the story posted correctly:

If you click on the time link for the story, you can preview the news feed story.

If you can't publish the test action, see if you have one of these common errors.

Error:

{
  "error": {
    "message": "(#200) Requires extended permission: publish_actions", 
    "type": "OAuthException", 
    "code": 200
  }
}

Reason:

You haven't authorized the app to publish to your timeline. Click on ''Get Access Token'' and click the ''Extended Permissions'' tab. Select the publish_actions permission and run your test again.

Error:

{
  "error": {
    "type": "Exception", 
    "message": "These users can't be tagged by your app: 100002768941660. Either they aren't developers of your app or your action haven't been approved for tagging.", 
    "code": 1611075
  }
}

Reason:

The user you're trying to tag is not an admin, developer or tester for your app. Go the Roles section for your app in the App Dashboard and add the user you want to tag to the appropriate role. You'll have to wait for that user to accept the request for you to add them to your app.

If you ever have issues using Graph API queries in your iOS app test the same queries out using the Graph API Explorer tool.


Step 4: Add the Meal Selection Flow

Now that you've set up and tested Open Graph publishing outside of your app, let's get back to the iOS code.

Continue setting up the UI by adding a view controller to allow the user to select a meal.

Create a new view controller by right-clicking on the ''Scrumptious'' folder > New File > Objective-C class, and name the class ''SCMealViewController''. Make sure to generate the corresponding NIB file as well.

Open up SCMealViewController.xib and add a Table View object to the view with the following properties: Style: Grouped; Section Height Header: 10; Section Height Footer: 10; X, Y (offset): 0, 0; Width, Height (size): 320, 460.

Next, wire up the meal selection table to the SCMealViewController implementation file:

  • Create an outlet for the Table View object and call it tableView.
  • Connect the dataSource outlet to the File's Owner.
  • Connect the delegate outlet to the File's Owner.

Next, in the SCMealViewController implementation file, add UITableViewDataSource and UITableViewDelegate to the list of protocols it conforms to:

@interface SCMealViewController ()
<UITableViewDataSource,
UITableViewDelegate> 

Then, create the table view data source by defining a property to hold the meal choices:

@interface SCMealViewController ()
<UITableViewDataSource,
UITableViewDelegate> {
    NSArray* _meals;
}

Set the view controller title and initialize the _meals array in the initWithNibName:bundle: custom initialization section:

self.title = @"Select a meal";

_meals = [NSArray arrayWithObjects:
            @"Cheeseburger", 
            @"Pizza",
            @"Hotdog",
            @"Italian",
            @"French",
            @"Chinese",
            @"Thai",
            @"Indian", nil];

Implement the UITableViewDatasource delegate and data source methods to display the data:

- (NSInteger)tableView:(UITableView *)tableView 
      numberOfRowsInSection:(NSInteger)section 
{
    return _meals.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView 
      cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [self.tableView 
        dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] 
                  initWithStyle:UITableViewCellStyleDefault 
                reuseIdentifier:CellIdentifier];
    }    

    cell.textLabel.text = [_meals objectAtIndex:indexPath.row];
    cell.imageView.image = [UIImage imageNamed:@"action-eating.png"];

    return cell;
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{
    return 1;
}

Define a callback in the SCViewController class that will be used to pass back information on the selected meal. Add the following to the SCViewController header file:

typedef void(^SelectItemCallback)(id sender, id selectedItem);

Next, open up the SCMealViewController header file and import the SCViewController.h file so you can reference the defined callback:

#import "SCViewController.h"

Add an interface property in SCMealViewController.h to hold the callback when a meal is selected:

@property (strong, nonatomic) SelectItemCallback selectItemCallback;

Next, open up the SCMealViewController implementation file and Synthesize this property:

@synthesize selectItemCallback = _selectItemCallback;

Then in the tableView:didSelectRowAtIndexPath: delegate method, add code to invoke the meal selection callback send the user to the previous view controller:

- (void)tableView:(UITableView *)tableView 
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (self.selectItemCallback) {
        self.selectItemCallback(self, [_meals objectAtIndex:indexPath.row]);
    }
    [self.navigationController popViewControllerAnimated:true];
}

Now that you've set up the meal selection view controller add code to push that controller when the user selects the relevant home menu option. Open up SCViewController.m and import the meal view controller:

#import "SCMealViewController.h"

Add a property for the meal selection view controller instance and the meal that will be selected in that controller:

@property (strong, nonatomic) SCMealViewController *mealViewController;
@property (strong, nonatomic) NSString* selectedMeal;

Synthesize the new properties:

@synthesize mealViewController = _mealViewController;
@synthesize selectedMeal = _selectedMeal;

Then, modify the tableView:didSelectRowAtIndexPath: delegate method to add a new case statement that is activated when the meal selection option is tapped:

case 0:
    if (!self.mealViewController) {
        __block SCViewController* myself = self;
        self.mealViewController = [[SCMealViewController alloc]
                  initWithNibName:@"SCMealViewController" bundle:nil];
        self.mealViewController.selectItemCallback = 
                    ^(id sender, id selectedItem) {
                      myself.selectedMeal = selectedItem;
                      [myself updateSelections];
        };
    }
    [self.navigationController 
                pushViewController:self.mealViewController 
                          animated:true];
    break;

Finally, modify the updateSelections method to save and display the selected meal. Add this code to the end of the method:

[self updateCellIndex:0 withSubtitle:(self.selectedMeal ?
                                          self.selectedMeal : 
                                          @"Select One")];

Build and run the project to make sure it runs without errors. Once you see the menu selection, select the ''What are you eating?'' menu option. You should see a list of meals to choose from. Selecting a meal and tapping the Back button should display your meal in the ''What are you eating?'' row.


Step 5: Add the Photo Selection Flow

In this step, you'll let the user select a photo from their Photo Library and get that ready to upload. In later steps, you'll implement the photo upload as part of a batch request when publishing the action.

You'll make the following changes to the SCMealViewController implementation file. Use of Apple's UIImagePickerController object to allow the user to select a photo from the Photo Library. First, add UIImagePickerControllerDelegate and UINavigationControllerDelegate to the list of protocols the SCViewController implementation class conforms to.

Next, define the properties you need to get the image: one property for the instance of UIImagePickerController, another for a UIPopoverController instance to present the image picker on iPads, and a property to hold the selected photo.

@property (strong, nonatomic) UIImagePickerController* imagePicker;
@property (strong, nonatomic) UIImage* selectedPhoto;
@property (strong, nonatomic) UIPopoverController *popover;

Synthesize these new properties:

@synthesize imagePicker = _imagePicker;
@synthesize selectedPhoto = _selectedPhoto;
@synthesize popover = _popover;

Remove the UIImagePickerController and UIPopoverController instances in the viewDidUnload method:

self.imagePicker = nil;
self.popover = nil;

Nil out the UIImagePickerController delegate in the dealloc method:

_imagePicker.delegate = nil;

Next, add logic to show the image picker when the user taps on the ''Got a picture?'' menu option. In tableView:didSelectRowAtIndexPath:, add a new case statement:

case 3: 
    if (!self.imagePicker) {
        self.imagePicker = [[UIImagePickerController alloc] init];
        self.imagePicker.delegate = self;

        // In a real app, we would probably let the user
        // either pick an image or take one using the camera.
        // For sample purposes in the simulator, the camera is not available.
        self.imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    }       
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
        // Can't use presentModalViewController for image picker on iPad
        if (!self.popover) {
            self.popover = [[UIPopoverController alloc]
                initWithContentViewController:self.imagePicker];
        }       
        CGRect rect = [tableView rectForRowAtIndexPath:indexPath];
        [self.popover
            presentPopoverFromRect:rect 
            inView:self.view 
            permittedArrowDirections:UIPopoverArrowDirectionAny 
            animated:YES];
    } else {
        [self presentModalViewController:self.imagePicker 
            animated:true];
    }
    break;

Implement the UIImagePickerControllerDelegate delegate method to save the selected photo in the selectedPhoto property, dismiss the image picker and invoke a method to update the home menu UI to display that a photo was selected:

- (void)imagePickerController:(UIImagePickerController *)picker 
        didFinishPickingImage:(UIImage *)image
                  editingInfo:(NSDictionary *)editingInfo
{
    self.selectedPhoto = image;

    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
        [self.popover dismissPopoverAnimated:YES];
    } else {
        [self dismissModalViewControllerAnimated:true];
    }

    [self updateSelections];
}

Modify the updateSelections method to show the user a photo is selected. Add this code to the end of the method:

[self updateCellIndex:3 withSubtitle:(self.selectedPhoto ? @"Ready" : @"Take one")];

Build and run the project to make sure it runs without errors. Once you see the menu selection, select the ''Got a picture?'' menu item. Select a photo in the Photo Library. You should see the ''Ready'' label in the ''Got a picture?'' row:


Step 6: Add the Publish Action Button

Now, finish setting up the UI by adding a submit button that publishes the Open Graph action through the iOS app.

In the SCViewController NIB file add a Round Rect Button object with the following properties: Title: ''Announce''; State Config: Disabled; Text Color: CCCCCC; Control Content Enabled: NO. Center it to the view's width and move it towards the bottom. Wire this up to an action named announce and also add an outlet named announceButton. The outlet will be used to enable/disable the button. You will only show the button if the user selects a meal. All other publish parameters are optional.

Your UI should look like this in Interface Builder:

Now, add logic at the end of the updateSelections method to enable the button:

self.announceButton.enabled = (self.selectedMeal != nil);

Build and run the project to make sure it runs without errors. Check that the announce button is disabled at the start and enabled when you select a meal. Tapping on the button should do nothing at this point. Next, you'll add the logic to publish to a user's timeline.


Step 7: Implement the Publish Action

Now, let's set up the logic to allow the user to publish an Open Graph action. Publishing an action involves making a Graph API call to the me/<YOUR_APP_NAMESPACE>:<ACTION_NAME> endpoint with the object URL and any optional parameters. You'll also need to make sure you ask for the publish_actions permissions. Since you may also be uploading a user selected photo and retrieving the photo information, you also need to ask for the user_photos permissions. You'll ask for the read permission: user_photos when the session is opened initially. You'll ask for the write permission: publish_actions in context, when you're about to publish the user's action. This will be added later in the announce button logic.

To ask for the required permissions, open SCAppDelegate.m and modify the openSession: method. Change this:

[FBSession openActiveSessionWithReadPermissions:nil
                                   allowLoginUI:YES
                              completionHandler:
                                   ^(FBSession *session, 
                                     FBSessionState state, NSError *error) {
                  [self sessionStateChanged:session state:state error:error];
}];    

To this:

NSArray *permissions = [NSArray arrayWithObjects:@"user_photos",  
                                                 nil];

[FBSession openActiveSessionWithReadPermissions:permissions
                                   allowLoginUI:YES
                              completionHandler:
                                   ^(FBSession *session, 
                                     FBSessionState state, NSError *error) {
                  [self sessionStateChanged:session state:state error:error];
}];    

The Open Graph meal object will be implemented as a new protocol you define named SCOGMeal. This new protocol incorporates the FBGraphObject protocol.

The Open Graph action eat and its parameters, including the object URL, will be implemented as a new protocol you define named SCOGEatMealAction that incorporates the FBOpenGraphAction protocol. This new protocol has an additional property representing the SCOGMeal object.

To define the new protocols, add a new file to the project. Select the Objective-C protocol template and name the protocol SCProtocols:

Next, open up the newly added SCProtocols.h file. You'll create your own protocol definition, so delete the default one that was created:

@protocol SCProtocols <NSObject>

@end

Next, include the Facebook SDK header as the new protocols are based on defined Facebook objects:

#import <FacebookSDK/FacebookSDK.h>

Add code to define the SCOGMeal object protocol:

@protocol SCOGMeal<FBGraphObject>

@property (retain, nonatomic) NSString *id;
@property (retain, nonatomic) NSString *url;

@end

Add code to define the SCOGEatMealAction object protocol:

@protocol SCOGEatMealAction<FBOpenGraphAction>

@property (retain, nonatomic) id<SCOGMeal> meal;

@end

Now, open up the SCViewController implementation file and include the new protocols header:

#import "SCProtocols.h"

Also include the FBRequest header that allows you to reference FBGraphObject objects:

#import <FacebookSDK/FBRequest.h>

Now, define a new method that returns a representation of the Open Graph meal object. The meal object will be a URL built dynamically based on the backend code you installed earlier:

- (id&lt;SCOGMeal>)mealObjectForMeal:(NSString*)meal 
{
    // This URL is specific to this sample, and can be used to
    // create arbitrary OG objects for this app; your OG objects
    // will have URLs hosted by your server.
    NSString *format =  
        @"https://&lt;YOUR_BACK_END>/repeater.php?"
        @"fb:app_id=&lt;YOUR_APP_ID>&og:type=%@&"
        @"og:title=%@&og:description=%%22%@%%22&"
        @"og:image=https://s-static.ak.fbcdn.net/images/devsite/attachment_blank.png&"
        @"body=%@";

    // We create an FBGraphObject object, but we can treat it as 
    // an SCOGMeal with typed properties, etc. See &lt;FacebookSDK/FBGraphObject.h> 
    // for more details.
    id&lt;SCOGMeal> result = (id&lt;SCOGMeal>)[FBGraphObject graphObject];

    // Give it a URL that will echo back the name of the meal as its title, 
    // description, and body.
    result.url = [NSString stringWithFormat:format, 
                   @"&lt;YOUR_APP_NAMESPACE>:meal", meal, meal, meal];

    return result;
}

Replace <YOUR_BACK_END> with your backend Site URL, <YOUR_APP_ID> with your app ID and <YOUR_APP_NAMESPACE> with your App Namespace.

Next, prepare the photo information that will be an optional part of the published action. If the user selects a photo, you'll upload the photo, get the source URL and pass it to the Graph API publish call. Define a new method to do this:

- (void)postPhotoThenOpenGraphAction
{
    FBRequestConnection *connection = [[FBRequestConnection alloc] init];

    // First request uploads the photo.
    FBRequest *request1 = [FBRequest 
        requestForUploadPhoto:self.selectedPhoto];
    [connection addRequest:request1
        completionHandler:
        ^(FBRequestConnection *connection, id result, NSError *error) {
            if (!error) {
            }
        }
            batchEntryName:@"photopost"
    ];

    // Second request retrieves photo information for just-created 
    // photo so we can grab its source.
    FBRequest *request2 = [FBRequest 
        requestForGraphPath:@"{result=photopost:$.id}"];
    [connection addRequest:request2
         completionHandler:
        ^(FBRequestConnection *connection, id result, NSError *error) {
            if (!error &&
                result) {
                NSString *source = [result objectForKey:@"source"];
                [self postOpenGraphActionWithPhotoURL:source];
            }
        }
    ];

    [connection start];
}

Don't worry about the error related to the undefined postOpenGraphActionWithPhotoURL: method. You'll define this next.

Once you have meal object and the optional photo source URL you can put the Graph API call together. Define a new method to do this:

- (void)postOpenGraphActionWithPhotoURL:(NSString*)photoURL
{
    // First create the Open Graph meal object for the meal we ate.
    id&lt;SCOGMeal> mealObject = [self mealObjectForMeal:self.selectedMeal];

    // Now create an Open Graph eat action with the meal, our location, 
    // and the people we were with.
    id&lt;SCOGEatMealAction> action = 
        (id&lt;SCOGEatMealAction>)[FBGraphObject graphObject];
    action.meal = mealObject;
    if (self.selectedPlace) {
        action.place = self.selectedPlace;
    }
    if (self.selectedFriends.count > 0) {
        action.tags = self.selectedFriends;
    }
    if (photoURL) {
        NSMutableDictionary *image = [[NSMutableDictionary alloc] init];
        [image setObject:photoURL forKey:@"url"];

        NSMutableArray *images = [[NSMutableArray alloc] init];
        [images addObject:image];

        action.image = images;
    }

    // Create the request and post the action to the 
    // "me/&lt;YOUR_APP_NAMESPACE>:eat" path.
    [FBRequestConnection startForPostWithGraphPath:@"me/&lt;YOUR_APP_NAMESPACE>:eat"
                             graphObject:action
                       completionHandler:
     ^(FBRequestConnection *connection, id result, NSError *error) {
         NSString *alertText;
         if (!error) {
             alertText = [NSString stringWithFormat:
                             @"Posted Open Graph action, id: %@",
                             [result objectForKey:@"id"]];
         } else {
             alertText = [NSString stringWithFormat:
                             @"error: domain = %@, code = %d",
                             error.domain, error.code];
         }
         [[[UIAlertView alloc] initWithTitle:@"Result" 
                                     message:alertText 
                                    delegate:nil 
                           cancelButtonTitle:@"Thanks!" 
                           otherButtonTitles:nil] 
          show]; 
     }
     ];
}

Replace <YOUR_APP_NAMESPACE> with your App Namespace.

Finally, fill in the announce: method that is invoked when the user taps the announce button. This first checks if publish_actions had been previously granted for your app on the user's device. If not, the permissions are requested with the required audience selector defaulted to the user's friends. If the permissions have been granted then the logic checks if a photo is available and uploads the photo before publishing, or simply calls the publishing method:

- (IBAction)announce:(id)sender
{
    if ([FBSession.activeSession.permissions 
            indexOfObject:@"publish_actions"] == NSNotFound) {  

        [FBSession.activeSession 
            requestNewPublishPermissions:[NSArray arrayWithObject:@"publish_actions"]
                              defaultAudience:FBSessionDefaultAudienceFriends   
                            completionHandler:^(FBSession *session, NSError *error) {   
                         if (!error) {  
                             // re-call assuming we now have the permission 
                             [self announce:sender];    
                         }  
        }]; 
    } else {
        if (self.selectedPhoto) {
            [self postPhotoThenOpenGraphAction];
        } else {
            [self postOpenGraphActionWithPhotoURL:nil];
        }
    }
}

Build and run the project to make sure it runs without errors. If necessary, log out and log back into the app to make sure you authorize the app again and accept the updated permissions. Publish a simple action with only the meal specified. You should see an alert message with the published action id:

You should also check your timeline's Activity Log to ensure the action published successfully and has the correct story.

If you run into any issues, try turning on logging by adding this code before the request call you're interested in debugging:

[FBSettings setLoggingBehavior:[NSSet 
                                   setWithObjects:FBLoggingBehaviorFBRequests,
                                   FBLoggingBehaviorFBURLConnections, 
                                   nil]];

Test the different additional scenarios like adding friends, a place and a photo. View the different types of stories published by going to your timeline's Activity Log on the desktop. (Hint: to view the how the story will render, click on the date next to the story in the Activity Log.)

Congratulations! You've successfully completed the tutorial and walked through many of the key Facebook features.


Next Steps

You may want to go through the following How Tos to learn more about Facebook features that can enrich your apps.

  • Fetch User Data: Learn how to customize the data you fetch for a user.

  • Publish to Feed: Learn how to publish a story to the user's timeline, ex: to update a user's status.

  • Send Requests: Learn how to engage users more and make your apps more viral.

  • Link To Your Native App: Learn how you to configure Open Graph story links to drive distribution back to your iOS app and optimize the user's experience.


Related Samples

  • Scrumptious
  • Handling Facebook API Errors: Graph API topic on error handling
Updated last Wednesday
Facebook © 2013 · English (US)
AboutAdvertisingCareersPlatform PoliciesPrivacy Policy