Building on the Twitter integration announced in iOS 5, Apple announced OS level integration of Facebook and SinaWeibo for iOS 6. This integration, using the new Social framework, makes incorporating sharing functionality and integrating a users social network into your applications easier and provides users with a consistent experience These APIs also make use of a single sign on (SSO) feature in iOS 6, which handles credential management for you. If you are developing an app targeted for iOS 5 or higher, you can still use the Social framework but need to degrade gracefully to the Facebook SDK for devices using versions prior to iOS 6.

The Social framework supports three types of social services in iOS 6: Facebook, Twitter and SinaWeibo. You will only see the SinaWeibo in preferences if you have a Chinese keyboard enabled. For advanced integration the most important class is the SLRequest, which provides a mechanism to issue requests to Facebook's Graph API.

There are two classes that make sharing or posting to a users social network easy in iOS6: UIActivityViewController and the SLComposeViewController.

UIActivityViewController

The first new class is the UIActivityViewController, which, seen below, presents a modal view with different options to share such as email, Twitter and Facebook. You will see the UIActivityViewController throughout iOS6 when a user selects the share button. No special frameworks or imports are needed here.

UIActivityViewController

The code below is all you need to open a post sheet to share a text message and a picture of a cat. Feel free to put in your own picture.

<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span class="kw5">NSString</span></a> <span class="sy0">*</span>text <span class="sy0">=</span> <span class="co3">@</span><span class="st0">"Cat"</span>;
UIImage <span class="sy0">*</span>image <span class="sy0">=</span> <span class="br0">[</span>UIImage imageNamed<span class="sy0">:</span><span class="co3">@</span><span class="st0">"cat"</span><span class="br0">]</span>;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span class="kw5">NSArray</span></a> <span class="sy0">*</span>activityItems <span class="sy0">=</span> <span class="br0">[</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span class="kw5">NSArray</span></a> arrayWithObjects<span class="sy0">:</span>text,image , <span class="kw2">nil</span><span class="br0">]</span>;
UIActivityViewController <span class="sy0">*</span>avc <span class="sy0">=</span> <span class="br0">[</span><span class="br0">[</span>UIActivityViewController alloc<span class="br0">]</span>
 initWithActivityItems<span class="sy0">:</span> activityItems applicationActivities<span class="sy0">:</span><span class="kw2">nil</span><span class="br0">]</span>;
<span class="br0">[</span>self presentViewController<span class="sy0">:</span>avc animated<span class="sy0">:</span><span class="kw2">YES</span> completion<span class="sy0">:</span><span class="kw2">nil</span><span class="br0">]</span>;

SLComposeViewController

If you are targeting one particular supported social network there is a streamlined method of creating a share sheet using SLComposeViewController (with supporting documentation). This is similar to the now deprecated Twitter framework and requires you to add the Social.framework to your project. Building on the last example, the snippet below creates a share sheet to create a Facebook Post view and add an image. One additional configurable setting would be the URL of the item being shared. One thing to note, SLComposeViewController conforms to UIAppearanceContainer so that the navigation bar and bar button items can be styled to meet your applications style.

<span class="kw1">if</span><span class="br0">(</span><span class="br0">[</span>SLComposeViewController isAvaliableForServiceType<span class="sy0">:</span>SLServiceTypeFacebook<span class="br0">]</span><span class="br0">)</span> <span class="br0">{</span> 
 SLComposeViewController<span class="sy0">*</span>fvc <span class="sy0">=</span> <span class="br0">[</span>SLComposeViewController
 composeViewControllerForServiceType<span class="sy0">:</span>SLServiceTypeFacebook<span class="br0">]</span>;
 <span class="br0">[</span>fvc setInitialText<span class="sy0">:</span><span class="co3">@</span><span class="st0">"Lhasa"</span><span class="br0">]</span>;
 <span class="br0">[</span>fvc addImage<span class="sy0">:</span><span class="br0">[</span>UIImage imageNamed<span class="sy0">:</span><span class="co3">@</span><span class="st0">"lhasa"</span><span class="br0">]</span><span class="br0">]</span>;
 <span class="br0">[</span>self presentViewController<span class="sy0">:</span>fvc animated<span class="sy0">:</span><span class="kw2">YES</span> completion<span class="sy0">:</span><span class="kw2">nil</span><span class="br0">]</span>;
<span class="br0">}</span>

After executing the code above you should be presented with a view controller similar to the one below. As you can see, the view controller handles all Facebook specific functionality such as assigning the album the photo should be uploaded to, adding or removing your location, and tagging any friends.

SLComposeViewController

Advanced Integration

Advanced integration requires a little more work, but considerably less than the official Facebook SDK. Advanced integration allows your app full access to the Facebook Graph API. On the Facebook developers page, the Graph API Explorer tool allows you to try your URL requests before you add them to your code.

To use advanced integration you first need to register your app in iTunes Connect. It can be in the "Prepare for Upload" stage, but you need the Apple ID of the app for the next step. Second, you must register your app in the Facebook Developer Portal, accessible by selecting Apps in the navigation bar and then selecting Create New App. The tabs for Basic, Permissions and Advanced need to be updated. Be sure to have your applications Bundle ID and iPhone/iPad App Store ID.

Using the Accounts framework in combination with the Social framework, you can create an ACAccountStore object so that you can request access the users Facebook information. You will need to create an NSDictionarythat contains a value for the key ACFacebookAppIdKey. This value is then retrieved from Facebook after registering your application. The Apple class reference for ACAcountStore, as of Oct 1, 2012, indicates that the ACFacebookPermisionsKey is optional. Unfortunately, it is not. You must include at least one ACFacebookPermissionsKey in the options dictionary. According to Facebook, it must be one of the following read permissions:email, user_birthday, or user_location. One other key is the ACFacebookAudienceKey which chooses who is allowed to see the post. Other read and publish permissions can be found at https://developers.facebook.com/docs/howtos/ios-6/. There are two items that you cannot get permission for with your app: the user's timeline and managing pages.

When the requestAccessToAccountsWithType: method is invoked, the user receives an alert prompt that resembles the image below asking if they want to give permission to your app to access their basic account information. If you request other permissions beyond the basic profile, such as friends_videos, another similar message will be displayed asking to access that information as well.

FacebookPermissionPrompt

The sample code below will get you started:

self.accountStore <span class="sy0">=</span> <span class="br0">[</span><span class="br0">[</span>ACAccountStore alloc<span class="br0">]</span>init<span class="br0">]</span>;
ACAccountType <span class="sy0">*</span>FBaccountType<span class="sy0">=</span> <span class="br0">[</span>self.accountStore accountTypeWithAccountTypeIdentifier<span class="sy0">:</span>
 ACAccountTypeIdentifierFacebook<span class="br0">]</span>;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span class="kw5">NSString</span></a> <span class="sy0">*</span>key <span class="sy0">=</span> <span class="co3">@</span><span class="st0">"987654"</span>; <span class="co2">//put your own key from FB here</span>
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span class="kw5">NSDictionary</span></a> <span class="sy0">*</span>dictFB <span class="sy0">=</span> <span class="co2">//use ACAccountStore to help create your dictionary</span>
<span class="br0">[</span>self.accountStore requestAccessToAccountsWithType<span class="sy0">:</span>FBaccountType options<span class="sy0">:</span>dictFB
 completion<span class="sy0">:</span> <span class="sy0">^</span><span class="br0">(</span><span class="kw4">BOOL</span> granted, <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSError_Class/"><span class="kw5">NSError</span></a> <span class="sy0">*</span>e<span class="br0">)</span> <span class="br0">{</span>
 <span class="kw1">if</span> <span class="br0">(</span>granted<span class="br0">)</span> <span class="br0">{</span>
 <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span class="kw5">NSArray</span></a> <span class="sy0">*</span>accounts <span class="sy0">=</span> <span class="br0">[</span>self.accountStore accountsWithAccountType<span class="sy0">:</span>FBaccountType<span class="br0">]</span>;
 <span class="co2">//it will always be the last object with SSO</span>
 self.facebookAccount <span class="sy0">=</span> <span class="br0">[</span>accounts lastObject<span class="br0">]</span>;
 <span class="br0">}</span> <span class="kw1">else</span> <span class="br0">{</span>
 <span class="co2">//Fail gracefully...</span>
 NSLog<span class="br0">(</span><span class="co3">@</span><span class="st0">"error getting permission %@"</span>,e<span class="br0">)</span>;
 <span class="br0">}</span> <span class="br0">}</span><span class="br0">]</span>;

Not only did requestAccessToAccountsWithType: get the account, but it also retrieved a token for the account. Apple has encapsulated the OAuth request with this method so the developer no longer needs to worry about managing the OAuth request themselves. The token received is necessary for subsequent calls. The SLRequest snippet below contains a property, account, from the ACAccount framework which holds that token. The code below shows how to use that account to grab the users information from the Facebook Graph API and convert it to an NSDictionary. Other URLs calls can be found on the Facebook developer page.

<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span class="kw5">NSURL</span></a> <span class="sy0">*</span>requestURL <span class="sy0">=</span> <span class="br0">[</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span class="kw5">NSURL</span></a> URLWithString<span class="sy0">:</span><span class="co3">@</span><span class="st0">"https://graph.facebook.com/me"</span><span class="br0">]</span>;
SLRequest <span class="sy0">*</span>request <span class="sy0">=</span> <span class="br0">[</span>SLRequest requestForServiceType<span class="sy0">:</span>SLServiceTypeFacebook
 requestMethod<span class="sy0">:</span>SLRequestMethodGET
 URL<span class="sy0">:</span>requestURL
 parameters<span class="sy0">:</span><span class="kw2">nil</span><span class="br0">]</span>;
 request.account <span class="sy0">=</span> self.facebookAccount;
 <span class="br0">[</span>request performRequestWithHandler<span class="sy0">:^</span><span class="br0">(</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/"><span class="kw5">NSData</span></a> <span class="sy0">*</span>data,
 <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSHTTPURLResponse_Class/"><span class="kw5">NSHTTPURLResponse</span></a> <span class="sy0">*</span>response,
 <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSError_Class/"><span class="kw5">NSError</span></a> <span class="sy0">*</span>error<span class="br0">)</span> <span class="br0">{</span>
 
 <span class="kw1">if</span><span class="br0">(</span><span class="sy0">!</span>error<span class="br0">)</span><span class="br0">{</span>
 <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span class="kw5">NSDictionary</span></a> <span class="sy0">*</span>list <span class="sy0">=</span><span class="br0">[</span>NSJSONSerialization JSONObjectWithData<span class="sy0">:</span>data
 options<span class="sy0">:</span>kNilOptions error<span class="sy0">:&</span>error<span class="br0">]</span>;
 NSLog<span class="br0">(</span><span class="co3">@</span><span class="st0">"Dictionary contains: %@"</span>, list <span class="br0">)</span>;
 <span class="br0">}</span>
 <span class="kw1">else</span><span class="br0">{</span>
 <span class="co2">//handle error gracefully</span>
 <span class="br0">}</span> 
 
 <span class="br0">}</span><span class="br0">]</span>;

Remember that the user may change their Facebook settings or the app token may time out. If you listen for an ACAccountStoreDidChangeNotification you can then call renewCredentialsForAccount: to prompt the user for permission.

 
<span class="sy0">-</span><span class="br0">(</span><span class="kw4">void</span><span class="br0">)</span>accountChanged<span class="sy0">:</span><span class="br0">(</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNotification_Class/"><span class="kw5">NSNotification</span></a> <span class="sy0">*</span><span class="br0">)</span>notif<span class="co2">//no user info associated with this notif</span>
<span class="br0">{</span>
 <span class="br0">[</span>self attemptRenewCredentials<span class="br0">]</span>;
<span class="br0">}</span>
<span class="sy0">-</span><span class="br0">(</span><span class="kw4">void</span><span class="br0">)</span>attemptRenewCredentials<span class="br0">{</span>
 <span class="br0">[</span>self.accountStore renewCredentialsForAccount<span class="sy0">:</span><span class="br0">(</span>ACAccount <span class="sy0">*</span><span class="br0">)</span>self.facebookAccount completion<span class="sy0">:^</span><span class="br0">(</span>ACAccountCredentialRenewResult renewResult, <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSError_Class/"><span class="kw5">NSError</span></a> <span class="sy0">*</span>error<span class="br0">)</span><span class="br0">{</span>
 <span class="kw1">if</span><span class="br0">(</span><span class="sy0">!</span>error<span class="br0">)</span>
 <span class="br0">{</span>
 <span class="kw1">switch</span> <span class="br0">(</span>renewResult<span class="br0">)</span> <span class="br0">{</span>
 <span class="kw1">case</span> ACAccountCredentialRenewResultRenewed<span class="sy0">:</span>
 NSLog<span class="br0">(</span><span class="co3">@</span><span class="st0">"Good to go"</span><span class="br0">)</span>;
 <span class="br0">[</span>self get<span class="br0">]</span>;
 <span class="kw2">break</span>;
 <span class="kw1">case</span> ACAccountCredentialRenewResultRejected<span class="sy0">:</span>
 NSLog<span class="br0">(</span><span class="co3">@</span><span class="st0">"User declined permission"</span><span class="br0">)</span>;
 <span class="kw2">break</span>;
 <span class="kw1">case</span> ACAccountCredentialRenewResultFailed<span class="sy0">:</span>
 NSLog<span class="br0">(</span><span class="co3">@</span><span class="st0">"non-user-initiated cancel, you may attempt to retry"</span><span class="br0">)</span>;
 <span class="kw2">break</span>;
 <span class="kw1">default</span><span class="sy0">:</span>
 <span class="kw2">break</span>;
 <span class="br0">}</span>
 
 <span class="br0">}</span>
 <span class="kw1">else</span><span class="br0">{</span>
 <span class="co2">//handle error gracefully</span>
 NSLog<span class="br0">(</span><span class="co3">@</span><span class="st0">"error from renew credentials%@"</span>,error<span class="br0">)</span>;
 <span class="br0">}</span>
 <span class="br0">}</span><span class="br0">]</span>;
<span class="br0">}</span>

Closing

This post presents ideas on the new Accounts and Social frameworks for using Facebook in your enterprise iOS 6 applications. It should give you the foundation needed to begin implementing Facebook integration in your applications. I've attached the source for TempFBapp. If you've got questions you may contact me at estroh@captechconsulting.com.