The Facebook SDK for iOS provides a way to publish to a user's timeline with the Graph API. This is an alternate to using the Feed Dialog to publish a story. You can also use this method to update a user's status.
The Facebook SDK's FBRequestConnection class has a convenience class method you can use to publish to a user's timeline: startWithGraphPath:parameters:HTTPMethod:completionHandler:. Pass USER_ID/feed to the Graph API path parameter, pass in the desired feed parameters and set ''POST'' as the HTTP method.
This document walks through the following:
Note: To see an example of using the SDK to make the API call, skip to the Publish the Story section.
Before you begin, make sure you already set up Facebook Login. This ensures you have the prerequisites and your app is ready for additional Facebook integration.
The completed sample allows users to log in with Facebook and publish a link on their timeline.
The implementation builds on top of Facebook Login, adding a button that opens up a view where the user can share a pre-defined link. The share view shows a preview of the post and a text field where the user can enter an optional message. When the user taps on the share button, a story is published to their timeline and an alert pops up with the story's ID.

The sample contains a main view controller that displays the initial view. You'll add a second view controller for the share preview. The share view controller is presented modally. When the user taps a share button, the story is published in the share view controller. Then, a confirmation alert displays. When the user dismisses the alert, the share view controller closes.
In this step, you'll add a button in the initial view controller. When the user clicks the button, the share view displays.
Make the following changes in your main view controller's nib file:
Round Rect Button object to the view. Set the button title to ''Publish''.When you've completed these steps, your implementation file should have the defined outlet and an empty publishButtonAction: action method.
If you followed the Facebook Login doc, you should have a sessionStateChanged: method defined in your view controller implementation file that controls the logged-in and logged-out UI. Modify this method to show the publish button only when the user is authenticated:
- (void)sessionStateChanged:(NSNotification*)notification {
if (FBSession.activeSession.isOpen) {
self.publishButton.hidden = NO;
[self.authButton setTitle:@"Logout" forState:UIControlStateNormal];
} else {
self.publishButton.hidden = YES;
[self.authButton setTitle:@"Login" forState:UIControlStateNormal];
}
}
This step sets up the share preview display. The story information is hard-coded for simplicity. At the end of this step, the display can be linked to the main view controller. You'll set up publishing in a later step.
First, add a new view controller for the share view display. From the Xcode File menu select New > File, select the Objective-C class template, name the class ShareViewController, make it a subclass of UIViewController and select the ''With XIB for user interface'' option.
Open up the ShareViewController nib file and add the UI components for the story preview and share. You'll add components for the published story's image, name, caption and description. You'll also add a text input field for a user message. Finally, you'll add a toolbar with two buttons, one to cancel and a second to publish the story.
Toolbar:
Toolbar object to the top of the view. Bar Button Item object represents the cancel button. Set the title to ''Cancel''.Flexible Space Bar Button Item object to the toolbar and place it to the right of the ''Cancel'' button. This ensures the button you add next appears on the right of the toolbar.Bar Button Item object to the toolbar and place it to the right of the space button. This represents the share button. Set the title to ''Share''.Message:
Text View object to the view below the toolbar. Stretch it out to take up most of the view's width.Image:
Image View object to the view below the ''Message'' text view, to the left of the main view.Aspect Fit.Name:
Label object to the view. Place it to the right of the ''Image'' image view and below the ''Message'' text view.System Bold.Caption:
Label object to the view. Place it below the ''Name'' label.Description:
Label object to the view. Place it below the ''Caption'' label.When you've added the UI components, you're nib should look like this:

In this step, you'll add logic to control the message UI. The message UI is implemented with a UITextView. You'll add logic to show the placeholder text when appropriate. You'll also add logic to dismiss the text input whenever the user taps outside the input field.
Open up the ShareViewController implementation file and list UITextViewDelegate as one of the protocols the class conforms to, so you can respond when the user start or stops editing text:
@interface ShareViewController ()
<UITextViewDelegate>
Next, define a constant string for the placeholder text by adding the following code before the class interface declaration:
NSString *const kPlaceholderPostMessage = @"Say something about this...";
Next, add a private helper method, which you'll use to set the placeholder message:
- (void)resetPostMessage
{
self.postMessageTextView.text = kPlaceholderPostMessage;
self.postMessageTextView.textColor = [UIColor lightGrayColor];
}
Then, implement UITextViewDelegate methods that handle text input editing changes. You'll clear the placeholder text whenever editing begins. You'll set the placeholder text when editing is done and the input text is empty:
- (void)textViewDidBeginEditing:(UITextView *)textView
{
// Clear the message text when the user starts editing
if ([textView.text isEqualToString:kPlaceholderPostMessage]) {
textView.text = @"";
textView.textColor = [UIColor blackColor];
}
}
- (void)textViewDidEndEditing:(UITextView *)textView
{
// Reset to placeholder text if the user is done
// editing and no message has been entered.
if ([textView.text isEqualToString:@""]) {
[self resetPostMessage];
}
}
Next, add logic to detect if a user taps outside the text view. When this is detected, you'll close the keyboard:
/*
* A simple way to dismiss the message text view:
* whenever the user clicks outside the view.
*/
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *) event
{
UITouch *touch = [[event allTouches] anyObject];
if ([self.postMessageTextView isFirstResponder] &&
(self.postMessageTextView != touch.view))
{
[self.postMessageTextView resignFirstResponder];
}
}
In this step, you'll configure the information displayed in the share preview. You'll define a new property that holds this data in an NSMutableDictionary object. You'll use the same property later on when making the API call to publish the story.
First, define the new property to hold the display data:
@property (strong, nonatomic) NSMutableDictionary *postParams;
Synthesize this new property:
@synthesize postParams = _postParams;
Set the display data value in the view controller's initWithNibName:bundle: method by adding the following code to the custom initialization section:
self.postParams =
[[NSMutableDictionary alloc] initWithObjectsAndKeys:
@"https://developers.facebook.com/ios", @"link",
@"https://developers.facebook.com/attachment/iossdk_logo.png", @"picture",
@"Facebook SDK for iOS", @"name",
@"Build great social apps and get more installs.", @"caption",
@"The Facebook SDK for iOS makes it easier and faster to develop Facebook integrated iOS apps.", @"description",
nil];
Pass the display data to the share view UI components by adding this code to the end of the viewDidLoad method:
// Show placeholder text
[self resetPostMessage];
// Set up the post information, hard-coded for this sample
self.postNameLabel.text = [self.postParams objectForKey:@"name"];
self.postCaptionLabel.text = [self.postParams
objectForKey:@"caption"];
[self.postCaptionLabel sizeToFit];
self.postDescriptionLabel.text = [self.postParams
objectForKey:@"description"];
[self.postDescriptionLabel sizeToFit];
In this step, you'll set up the story's image display. You'll load the image data asynchronously to ensure the share view display isn't blocked while the image is fetched.
First, define properties to hold the image data and the image connection request:
@property (strong, nonatomic) NSMutableData *imageData; @property (strong, nonatomic) NSURLConnection *imageConnection;
Synthesize these new properties:
@synthesize imageData = _imageData; @synthesize imageConnection = _imageConnection;
In the viewDidLoad method, start the image request by adding this code to the end of the method:
// Kick off loading of image data asynchronously so as not
// to block the UI.
self.imageData = [[NSMutableData alloc] init];
NSURLRequest *imageRequest = [NSURLRequest
requestWithURL:
[NSURL URLWithString:
[self.postParams objectForKey:@"picture"]]];
self.imageConnection = [[NSURLConnection alloc] initWithRequest:
imageRequest delegate:self];
Next, cancel any active connections by adding this code to the end of the viewDidUnload method:
if (self.imageConnection) {
[self.imageConnection cancel];
self.imageConnection = nil;
}
Finally, implement the NSURLConnection delegate methods to handle the incoming request data. You'll load the preview image when the image data is successfully retrieved:
- (void)connection:(NSURLConnection*)connection
didReceiveData:(NSData*)data{
[self.imageData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
// Load the image
self.postImageView.image = [UIImage imageWithData:
[NSData dataWithData:self.imageData]];
self.imageConnection = nil;
self.imageData = nil;
}
- (void)connection:(NSURLConnection *)connection
didFailWithError:(NSError *)error{
self.imageConnection = nil;
self.imageData = nil;
}
In this step, you'll implement the cancel action.
First, fill out the cancelButtonAction: method to dismiss the share view when the user taps the ''Cancel'' button:
- (IBAction)cancelButtonAction:(id)sender {
[[self presentingViewController]
dismissModalViewControllerAnimated:YES];
}
In this step, you'll set up the logic that presents the share view when the publish button is tapped in the main view.
Open the main view controller and import the ShareViewController class, so you can initialize and present it:
#import "ShareViewController.h"
Next, fill out the publishButtonAction: implementation to initialize and present the share view controller:
- (IBAction)publishButtonAction:(id)sender {
ShareViewController *viewController = [[ShareViewController alloc]
initWithNibName:@"ShareViewController"
bundle:nil];
[self presentViewController:viewController animated:YES completion:nil];
}
Build and run the project to make sure it runs without errors. Once authenticated, tap ''Publish'' and verify that the share preview UI looks good. Make any necessary adjustments to the UI components. Test that the message input placeholder text is shown and cleared correctly. Tap outside the message to make sure the keyboard closes. Finally, verify that tapping the cancel button dismisses the share view.
In this final step, you'll add logic to publish the story. Before publishing the story you'll check if the user had previously granted you publish_actions permissions and if not, you'll request this permission.
Open up the ShareViewController implementation file and import the Facebook SDK so you can make the publish request:
#import <FacebookSDK/FacebookSDK.h>
Next, add a helper method that will publish the story:
- (void)publishStory
{
[FBRequestConnection
startWithGraphPath:@"me/feed"
parameters:self.postParams
HTTPMethod:@"POST"
completionHandler:^(FBRequestConnection *connection,
id result,
NSError *error) {
NSString *alertText;
if (error) {
alertText = [NSString stringWithFormat:
@"error: domain = %@, code = %d",
error.domain, error.code];
} else {
alertText = [NSString stringWithFormat:
@"Posted action, id: %@",
[result objectForKey:@"id"]];
}
// Show the result in an alert
[[[UIAlertView alloc] initWithTitle:@"Result"
message:alertText
delegate:self
cancelButtonTitle:@"OK!"
otherButtonTitles:nil]
show];
}];
}
Next, fill out the shareButtonAction: method to ask for publish the story after checking if you have been granted publish_actions permissions for the user on this device:
- (IBAction)shareButtonAction:(id)sender {
// Hide keyboard if showing when button clicked
if ([self.postMessageTextView isFirstResponder]) {
[self.postMessageTextView resignFirstResponder];
}
// Add user message parameter if user filled it in
if (![self.postMessageTextView.text
isEqualToString:kPlaceholderPostMessage] &&
![self.postMessageTextView.text isEqualToString:@""]) {
[self.postParams setObject:self.postMessageTextView.text
forKey:@"message"];
}
// Ask for publish_actions permissions in context
if ([FBSession.activeSession.permissions
indexOfObject:@"publish_actions"] == NSNotFound) {
// No permissions found in session, ask for it
[FBSession.activeSession
requestNewPublishPermissions:
[NSArray arrayWithObject:@"publish_actions"]
defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:^(FBSession *session, NSError *error) {
if (!error) {
// If permissions granted, publish the story
[self publishStory];
}
}];
} else {
// If permissions present, publish the story
[self publishStory];
}
}
An alert appears after the story is published whether the request succeeds or fails. When the alert is dismissed, you'll dismiss the share view controller. To respond to the alert being dismissed, first add UIAlertViewDelegate to the list of protocols the ShareViewController class conforms to.
Next, implement the UIAlertView delegate method that is notified when the alert is dismissed and dismiss the share view:
- (void) alertView:(UIAlertView *)alertView
didDismissWithButtonIndex:(NSInteger)buttonIndex
{
[[self presentingViewController]
dismissModalViewControllerAnimated:YES];
}
Build and run the project to make sure it runs without errors. Once authenticated, tap ''Publish''. Then, on the share view, enter a message and tap ''Share''. You should see the permissions dialog or permissions alert (iOS6+) asking for publish permissions. If you allow publish permissions you should see an alert confirming that the story published. Check your timeline to verify the story published correctly.

Feel free to modify the code and test your own links in the published story.
The Graph API Explorer provides a way for you to debug any Graph API issues you're seeing. If you're having problems publishing a story, try it with the Graph API Explorer, as it may give you more error into and help you out.
JustRequestSample: sample included in the SDK that shows how to use Facebook request classes.