Facebook Developers
DocsToolsSupportNewsApps
Log In
  • Social Plugins
  • Facebook Login
  • Open Graph
  • Facebook APIs
  • Games
  • Payments
  • App Center
  • Promote Your App
  • iOS
  • Android
  • JavaScript
  • PHP
  • More SDKs
  • Topics
    • Facebook SDK for iOS
  • Authentication
    • Facebook Login with iOS
    • iOS 6 Integration
    • Understanding Sessions
    • Handling App Links
  • Data Access
    • Fetch User Data
    • Run FQL Queries
  • Sharing & Distribution
    • Sharing on iOS
    • Publish to Feed
    • iOS Share Sheet
    • Feed Dialog
    • Link To Your Native App
    • Send Requests
    • Setup for App Center
  • Customization
    • Add Search to Friend Selector
    • Manage Your Own Token Cache
    • Share an App ID Across Apps
  • Optimization
    • Batch Requests
    • Caching
    • Select Friends by Device
    • Handling Errors

Caching

Documentation › Caching

The Facebook SDK for iOS provides a caching feature that lets you pre-fetch data for friends and nearby places. This data is cached and available to your app before you need to present it to the users. Whenever the friend or nearby place selector displays, any cached data appears before fresh info is fetched from the server. Pre-fetching the data at the correct time allows you to provide a better user experience, because users don't have to wait for that first set of data to display.

We'll walk through how to pre-fetch data for friends and nearby places, and then discuss scenarios where pre-fetching is useful.

This document walks through the following topics:

  • Prerequisites
  • Sample Overview
  • Step 1: Set Up the Friend Selector Trigger
  • Step 2: Set Up a Basic Friend Selector
  • Step 3: Pre-fetch Friend Data
  • Step 4: Pre-fetch Additional Friend Info
  • Step 5: Set Up the Nearby Place Selector Trigger
  • Step 6: Set Up a Basic Nearby Place Selector
  • Step 7: Pre-fetch Place Data
  • Troubleshooting
  • Additional Info

Prerequisites

Before you begin, make sure you've already set up Facebook Login. This ensures you have the prerequisites and your app is ready for additional Facebook integration.


Sample Overview

The completed sample allows users to log in with Facebook and select a friend or place near Facebook headquarters. When a friend is selected, the friend's first name displays with the person's bio, if available. When a place is selected, the place name, city and state display.

The implementation builds on top of Facebook Login, adding two buttons. One button shows the friend selector and the second button shows the nearby place selector. When the user authenticates, friend and place data is pre-fetched and cached.



Step 1: Set Up the Friend Selector Trigger

In this step, you'll add a button in the initial view controller. When the user clicks the button, the friend selector displays.

Make the following changes in your main view controller's nib file:

  • Add a Round Rect Button object to the view. Set the button title to ''Show Friends''.
  • Hide the ''Show Friends'' button initially. You only want to display the button after the user authenticates.
  • Add an action to the ''Show Friends'' button and attach this action to your main view controller's implementation file. Name the action ''showFriendsAction''.
  • Add an outlet for the ''Show Friends'' button to your view controller's implementation file so that it's private. Name the outlet ''showFriendsButton''.

When you've completed these steps, your implementation file should have the defined outlet and an empty showFriendsAction: 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 friend selector button only when the user is authenticated:

- (void)sessionStateChanged:(NSNotification*)notification {
    if (FBSession.activeSession.isOpen) {
        self.showFriendsButton.hidden = NO;
        [self.authButton setTitle:@"Logout" forState:UIControlStateNormal];
    } else {
        self.showFriendsButton.hidden = YES;
        [self.authButton setTitle:@"Login" forState:UIControlStateNormal];
    }
}

Step 2: Set Up a Basic Friend Selector

In this step, you setup a basic friend selector without taking advantage of the friend data caching features.

Open the view controller implementation file and add the FBFriendPickerDelegate as one of the protocols the view controller implementation conforms to. Add this delegate to the view controller implementation.

@interface ViewController ()
<FBFriendPickerDelegate>

Next, fill out the showFriendsAction: method implementation to trigger the friend selector display. In the code you'll initialize a FBFriendPickerViewController object, configure the properties, set the delegate to the current class, load the data and then show the friend selector modally.

- (IBAction)showFriendsAction:(id)sender {    
    // Initialize the friend picker
    FBFriendPickerViewController *friendPickerController = 
        [[FBFriendPickerViewController alloc] init];
    
    // Configure the picker ...
    friendPickerController.title = @"Show Friends";
    // Set this view controller as the friend picker delegate
    friendPickerController.delegate = self;
    // Allow only a single friend to be selected
    friendPickerController.allowsMultipleSelection = NO;
    
    // Fetch the data
    [friendPickerController loadData];
    
    // Present view controller modally.e the deprecated
    if ([self
         respondsToSelector:@selector(presentViewController:animated:completion:)]) {
        // iOS 5+
        [self presentViewController:friendPickerController 
                           animated:YES 
                         completion:nil];
    } else {
        [self presentModalViewController:friendPickerController animated:YES];
    }
}

Then, implement the FBFriendPickerDelegate delegate methods to handle the done and cancel buttons. You'll simply dismiss the modal view controller:

- (void)facebookViewControllerCancelWasPressed:(id)sender
{
    [self dismissModalViewControllerAnimated:YES];
    
}

- (void)facebookViewControllerDoneWasPressed:(id)sender
{
    [self dismissModalViewControllerAnimated:YES];
}

Build and run the project to make sure it runs without errors. Tap the ''Login'' button to log in with Facebook. Once you're authenticated, you should see the ''Show Friends'' button. Tap ''Show Friends'' to show the friend selector. Test that the cancel and done buttons close the friend selector. You can also test pre-fetching that should not be set up at this point. If you can, turn off your internet connection and tap ''Show Friends''. Data should not display; you should see an error in the Xcode console.


Step 3: Pre-fetch Friend Data

In this step, you'll pre-fetch friend data when the user is authenticated. Modify the sessionStateChanged: method to make a call to the FBFriendPickerViewController class method cacheDescriptor to pre-fetch the data.

Copy this code:

FBCacheDescriptor *friendCacheDescriptor = 
    [FBFriendPickerViewController cacheDescriptor];
[friendCacheDescriptor prefetchAndCacheForSession:FBSession.activeSession];

And then paste it at the end of this clause:

if (FBSession.activeSession.isOpen) {

Build and run the project to make sure it runs without errors. Once authenticated, tap the ''Show Friends'' button to check the friend selector functionality. To test caching, rerun your app, wait a minute and then turn off internet access again. This ensures the app has a chance to fetch the data in the background.

Tap the ''Show Friends'' button. You should see friend names and may or may not see their profile pictures. You should also see an error in the Xcode console as it fails to fetch fresh data. Turn internet access on again and verify that triggering the friend selector shows all the friend info.


Step 4: Pre-fetch Additional Friend Info

In this step, you'll pre-fetch friend info and display it when the user selects a friend.

The FBFriendPickerViewController class fetches the following friend info by default: id, name, first_name, middle_name, last_name and picture. You can fetch additional data by passing the additional required field info to the fieldsForRequest property of the FBFriendPickerViewController instance. You can also pre-fetch additional info by calling the cacheDescriptorWithUserID:fieldsForRequest: class method instead of cacheDescriptor.

To make sure your app can retrieve friend bio info, your app needs the friends_about_me permission. If you followed the Facebook Login doc, you should have a openSessionWithAllowLoginUI: method defined in your app delegate implementation file. Open the app delegate implementation file and modify the FBSession initialization section to request this permission:

- (BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI {
    NSArray *permissions = [[NSArray alloc] initWithObjects:
                            @"friends_about_me",
                            nil];
    return [FBSession openActiveSessionWithReadPermissions:permissions
                                              allowLoginUI:allowLoginUI
                                         completionHandler:^(FBSession *session,
                                                         FBSessionState state,
                                                         NSError *error) {
                                         [self sessionStateChanged:session
                                                             state:state
                                                             error:error];
                                     }];
}

Now, you need to define a new protocol to represent friend info that includes bio data. This new protocol should also conform to FBGraphUser, the protocol that defines basic friend info. To define the new protocol, add a new file to the project. Select the Objective-C protocol template and name the protocol CacheProtocols.

Next, open up the newly added CacheProtocols.h file. You'll create your own protocol definition, so replace the contents of the file with the following:

#import <Foundation/Foundation.h>
#import <FacebookSDK/FacebookSDK.h>

@protocol CacheGraphFriend <FBGraphUser>

@property (nonatomic, retain) NSString *bio;

@end

Now, open up your view controller implementation file and include your new protocol:

#import "CacheProtocols.h"

Add a property to hold the extra field info we want for a friend:

@property (readwrite, copy, nonatomic) NSSet *extraFieldsForFriendRequest;

Synthesize this new property:

@synthesize extraFieldsForFriendRequest = _extraFieldsForFriendRequest;

Set the property value by adding the following code to the viewDidLoad method, just before the call to the app delegate's openSessionWithAllowLoginUI: method:

self.extraFieldsForFriendRequest = [NSSet setWithObjects:@"bio", nil];

In the showFriendsAction: method, add the following statement just before the call to loadData:

friendPickerController.fieldsForRequest = self.extraFieldsForFriendRequest;

That takes care of getting the extra field info when fetching a fresh copy of friends. You'll need to request this extra info when the friend data is pre-fetched. To do that, go to the sessionStateChanged: method and replace the following statement:

FBCacheDescriptor *cacheDescriptor = [FBFriendPickerViewController cacheDescriptor];

With the following statement:

FBCacheDescriptor  *friendCacheDescriptor = [FBFriendPickerViewController
    cacheDescriptorWithUserID:nil
             fieldsForRequest:self.extraFieldsForFriendRequest];

Now, let's add code to display the additional friend data, so we can test that it's fetched correctly. Implement the FBFriendPickerDelegate method that detects a selection and shows an alert with friend data:

- (void)friendPickerViewControllerSelectionDidChange:
(FBFriendPickerViewController *)friendPicker
{
    [self dismissModalViewControllerAnimated:YES];
    if (friendPicker.selection) {
        NSArray *friends = friendPicker.selection;
        id<CacheGraphFriend> friend = [friends objectAtIndex:0];

        NSString *message = @"";
        if (friend.bio && ![friend.bio isEqualToString:@""]) {
            message = [message stringByAppendingString:friend.bio];
        }
        UIAlertView *alert = [[UIAlertView alloc]
                              initWithTitle:friend.first_name
                              message:message
                              delegate:nil
                              cancelButtonTitle:@"OK"
                              otherButtonTitles:nil, nil];
        [alert show];
    }
}

Build and run the project to make sure it runs without errors. Once authenticated, tap the ''Show Friends'' button and select a friend. The friend selector should close and friend info displayed, including any available bio info:



Step 5: Set Up the Nearby Place Selector Trigger

In this step, you'll add a button in the initial view controller. When the user clicks the button, the nearby place selector displays.

Make the following changes in your main view controller's nib file:

  • Add a Round Rect Button object to the view. Set the button title to ''Show Nearby''.
  • Make the ''Show Nearby'' button hidden initially. You only want to display the button after the user authenticates.
  • Add an action to the ''Show Nearby'' button and attach it to your main view controller's implementation file. Name the action ''showNearbyAction''.
  • Add an outlet for the ''Show Nearby'' button to your view controller's implementation file so that it's private. Name the outlet ''showNearbyButton''.

When you've completed these steps, your implementation file should have the defined outlet and an empty showNearbyAction: action method.

Modify the sessionStateChanged: method in the view controller implementation file to show the nearby place selector button only when the user is authenticated. Add the following statement in the if clause of the session open check:

self.showNearbyButton.hidden = NO;

Add the following statement in the else clause of the session open check:

self.showNearbyButton.hidden = YES;

Step 6: Set Up a Basic Nearby Place Selector

In this step, you setup a basic nearby place selector without taking advantage of the place data caching features. We'll simplify this sample even further by hard coding the user's current location to Facebook headquarters in Menlo Park. Feel free to replace this with your location. You'll use the Core Location Framework help define this hard-coded current location.

Add the Core Location Framework to the project:


Open up the view controller implementation file and import the Core Location framework:

#import <CoreLocation/CoreLocation.h> 

Define a property to hold the location info:

@property (assign, nonatomic) CLLocationCoordinate2D searchLocation;

Synthesize the property:

@synthesize searchLocation = _searchLocation;

Set the location in the viewDidLoad method, just before the call to the app delegate's openSessionWithAllowLoginUI: method:

self.searchLocation = CLLocationCoordinate2DMake(37.483253, -122.150037);

Add the FBPlacePickerDelegate as one of the protocols the view controller implementation conforms to. Add this delegate to the view controller implementation.

@interface ViewController ()
<FBFriendPickerDelegate,
 FBPlacePickerDelegate>

Next, fill out the showNearbyAction: method implementation to trigger the nearby place selector display. In the code, you'll initialize a FBPlacePickerViewController object, configure the properties, set the delegate to the current class, load the data and then show the nearby place selector modally.

- (IBAction)showNearbyAction:(id)sender {    
    // Initialize the place picker
    FBPlacePickerViewController *placePickerController =
        [[FBPlacePickerViewController alloc] init];
    
    // Configure the picker ...
    placePickerController.title = @"Show Nearby";
    // Set this view controller as the place picker delegate
    placePickerController.delegate = self;
    // Set the search criteria
    placePickerController.locationCoordinate = self.searchLocation;
    placePickerController.radiusInMeters = 1000;
    placePickerController.resultsLimit = 20;
    
    // Fetch the data
    [placePickerController loadData];
    
    // Present view controller modally.
    if ([self
         respondsToSelector:@selector(presentViewController:animated:completion:)]) {
        // iOS 5+
        [self presentViewController:placePickerController animated:YES completion:nil];
    } else {
        [self presentModalViewController:placePickerController animated:YES];
    }
}

Implement the FBPlacePickerDelegate method that notifies the delegate of a place selection. Dismiss the nearby place selector when a place is selected and display the selected place's name, city and state:

- (void)placePickerViewControllerSelectionDidChange:
(FBPlacePickerViewController *)placePicker
{
    [self dismissModalViewControllerAnimated:YES];
    if (placePicker.selection) {
        UIAlertView *alert = [[UIAlertView alloc]
                              initWithTitle:placePicker.selection.name
                              message:[NSString
                                       stringWithFormat:@"%@, %@",
                                       placePicker.selection.location.city,
                                       placePicker.selection.location.state]
                              delegate:nil
                              cancelButtonTitle:@"OK"
                              otherButtonTitles:nil, nil];
        [alert show];
    }
}

Build and run the project to make sure it runs without errors. Once you're authenticated, you should see the ''Show Nearby'' button. Tap ''Show Nearby'' to show the nearby place selector. Test that selecting a place dismisses the selector and displays the place's name, city and state:


If you can, rerun your app from the start and turn off your internet connection. When you tap on ''Show Nearby'', no data should display;you should see an error logged in the Xcode console.


Step 7: Pre-fetch Place Data

In this step, you'll pre-fetch nearby place data when the user is authenticated. Modify the sessionStateChanged: method to make a call to the FBPlacePickerViewController class method cacheDescriptorWithLocationCoordinate:radiusInMeters:searchText:resultsLimit:fieldsForRequest: to pre-fetch the data. At the end of the following if clause:

if (FBSession.activeSession.isOpen) {

Add this code:

FBCacheDescriptor *placeCacheDescriptor =
        [FBPlacePickerViewController
         cacheDescriptorWithLocationCoordinate:self.searchLocation
         radiusInMeters:1000
         searchText:nil
         resultsLimit:20
         fieldsForRequest:nil];
[placeCacheDescriptor prefetchAndCacheForSession:FBSession.activeSession];

Build and run the project to make sure it runs without errors. Once authenticated, tap the ''Show Nearby'' button to check the nearby place selector functionality. To test caching, rerun your app, wait a minute, and then turn off internet access. This ensures the app has a chance to fetch the data in the background.

Tap the ''Show Nearby'' button You should see the place names and you may or may not see the place profile pictures. Test that selecting a place dismisses the selector and displays the place's name, city and state. Turn internet access on again and verify that triggering the nearby place selector shows all the place info.


Troubleshooting

If you're using Facebook SDK 3.0.6 for iOS and your app crashes when the nearby place selector is being displayed, then check this migration setting:

Until a fix is in place you'll want to keep this migration setting to Disabled. Alternatively, you could disable place picture loading by adding the following line of code before loading the nearby place selector's data:

placePickerController.itemPicturesEnabled = NO;

Additional Info

  • FBFriendPickerViewController: reference for the friend selector class.
  • FBPlacePickerViewController: reference for the nearby place selector class.
  • Scrumptious: sample included in the SDK that shows caching for friend and place data.
Updated on Monday
Facebook © 2013 · English (US)
AboutAdvertisingCareersPlatform PoliciesPrivacy Policy