Skip to content

Commit

Permalink
Adds caching support for friend picker, and scrumptious
Browse files Browse the repository at this point in the history
Summary:
Adds API and internal support for caching of the friend picker. This includes
addition of two public classes: FBCacheDescriptor, and FBFriendPickerCacheDescriptor.
Also included is a place-holder class (not yet public) for FBPlacePickerCacheDescriptor.

Test Plan: Added unit tests, ran them

Reviewers: clang, mmarucheck

Reviewed By: clang

CC: gregschechte, platform-diffs@lists, yariv

Differential Revision: https://phabricator.fb.com/D490965

Task ID: 1093164
  • Loading branch information
onebit committed Jun 12, 2012
1 parent f2c6903 commit c01c758
Show file tree
Hide file tree
Showing 26 changed files with 714 additions and 48 deletions.
Expand Up @@ -46,7 +46,6 @@
856DC2191577F105001FA6A6 /* Icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon@2x.png"; sourceTree = "<group>"; };
8592BE3915816CBF00056680 /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; };
8592BE3C15816CCC00056680 /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; };
8592BE3E158173A000056680 /* Scrumptious.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = Scrumptious.entitlements; sourceTree = "<group>"; };
85954AE1155889A200FABA9A /* SCProtocols.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SCProtocols.h; sourceTree = "<group>"; };
B9C1C35815129F0E008FA5D1 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; };
B9C1C35A1512A637008FA5D1 /* SCMealViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCMealViewController.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -135,7 +134,6 @@
B9CD0A79150EA4DD00560A93 /* Scrumptious */ = {
isa = PBXGroup;
children = (
8592BE3E158173A000056680 /* Scrumptious.entitlements */,
B9CD0A98150EBFBD00560A93 /* images */,
B9CD0A7A150EA4DD00560A93 /* Supporting Files */,
B9CD0A82150EA4DD00560A93 /* SCAppDelegate.h */,
Expand Down
5 changes: 5 additions & 0 deletions samples/Scrumptious/scrumptious/SCAppDelegate.m
Expand Up @@ -14,6 +14,7 @@
* limitations under the License.
*/

#import <FBiOSSDK/FacebookSDK.h>
#import "SCAppDelegate.h"
#import "SCViewController.h"
#import "SCLoginViewController.h"
Expand Down Expand Up @@ -71,6 +72,10 @@ - (void)sessionStateChanged:(FBSession *)session
if ([[topViewController modalViewController] isKindOfClass:[SCLoginViewController class]]) {
[topViewController dismissModalViewControllerAnimated:YES];
}

// fetch and cache the friends for the friend picker as soon as possible
FBCacheDescriptor *cacheDescriptor = [FBFriendPickerViewController cacheDescriptor];
[cacheDescriptor prefetchAndCacheForSession:session];
}
break;
case FBSessionStateClosed:
Expand Down
2 changes: 1 addition & 1 deletion samples/Scrumptious/scrumptious/scrumptious-Prefix.pch
Expand Up @@ -15,7 +15,7 @@
*/

//
// Prefix header for all source files of the 'scrumptious' target in the 'scrumptious' project
// Prefix header for all source files of the 'Scrumptious' target in the 'Scrumptious' project
//

#ifdef __OBJC__
Expand Down
40 changes: 40 additions & 0 deletions src/FBCacheDescriptor.h
@@ -0,0 +1,40 @@
/*
* Copyright 2012 Facebook
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#import <Foundation/Foundation.h>
#import "FBSession.h"

/*!
@class
@abstract
Base class from which CacheDescriptors derive, provides a method to fetch data for later use
@discussion
Cache descriptors allow your application to specify the arguments that will be
later used with another object, such as the FBFriendPickerViewController. By using a cache descriptor
instance, an application can choose to fetch data ahead of the point in time where the data is needed.
*/
@interface FBCacheDescriptor : NSObject

/*!
@method
@abstract
Fetches and caches the data described by the cache descriptor instance, for the given session.
*/
- (void)prefetchAndCacheForSession:(FBSession*)session;

@end
26 changes: 26 additions & 0 deletions src/FBCacheDescriptor.m
@@ -0,0 +1,26 @@
/*
* Copyright 2012 Facebook
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#import "FBCacheDescriptor.h"

@implementation FBCacheDescriptor

- (void)prefetchAndCacheForSession:(FBSession *)session {
// we are treating this method as abstract virtual here
[self doesNotRecognizeSelector:_cmd];
}

@end
91 changes: 91 additions & 0 deletions src/FBFriendPickerCacheDescriptor.h
@@ -0,0 +1,91 @@
/*
* Copyright 2012 Facebook
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#import <Foundation/Foundation.h>
#import "FBCacheDescriptor.h"

/*
@class
@abstract
Represents the data needed by an FBFriendPickerViewController, in order to construct
the necessary request to populate the view; instances of FBFriendPickerCacheDescriptor
are used to fetch data ahead of the point when the data is used to populate a display.
@discussion
A common use of an FBFriendPickerCacheDescriptor instance, is to allocate an instance
at the point when a session is opened, and then call prefetchAndCacheForSession. This
causes the API to fetch and cache the data needed by the FBFriendPickerViewController.
If at some point the user goes to select friends, the FBFriendPickerViewController
will first check the cache for a copy of the friends list, and then after displaying
whatever cached data is available, then it will fetch a fresh copy of the friends list.
@unsorted
*/
@interface FBFriendPickerCacheDescriptor : FBCacheDescriptor

/*
@method
@abstract
Initializes an instance with default values for populating
a FBFriendPickerViewController, at some later point.
*/
- (id)init;

/*
@method
@abstract
Initializes an instance specifying the userID to use for populating
a FBFriendPickerViewController, at some later point.
*/
- (id)initWithUserID:(NSString*)userID;

/*
@method
@abstract
Initializes an instance specifying the fields to use for populating
a FBFriendPickerViewController, at some later point.
*/
- (id)initWithFieldsForRequest:(NSSet*)fieldsForRequest;

/*
@method
@abstract
Initializes an instance specifying the userID and fields to use for populating
a FBFriendPickerViewController, at some later point.
@param userID fbid of the user whose friends we wish to display; nil='me'
@param fieldsForRequest set of additional fields to include in request for friends
*/
- (id)initWithUserID:(NSString*)userID fieldsForRequest:(NSSet*)fieldsForRequest;

/*
@abstract
Fields to use when fetching data for the view
*/
@property (nonatomic, readonly, copy) NSSet *fieldsForRequest;

/*
@abstract
Indicates the fbid of the user whose friends are being viewed
*/
@property (nonatomic, readonly, copy) NSString *userID;

@end
135 changes: 135 additions & 0 deletions src/FBFriendPickerCacheDescriptor.m
@@ -0,0 +1,135 @@
/*
* Copyright 2012 Facebook
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#import "FBFriendPickerCacheDescriptor.h"
#import "FBFriendPickerViewController+Internal.h"
#import "FBSession.h"
#import "FBRequest.h"
#import "FBRequestConnection.h"
#import "FBGraphObjectTableDataSource.h"
#import "FBGraphObjectPagingLoader.h"

@interface FBFriendPickerCacheDescriptor () <FBGraphObjectPagingLoaderDelegate>

@property (nonatomic, readwrite, copy) NSSet *fieldsForRequest;
@property (nonatomic, readwrite, copy) NSString *userID;
@property (nonatomic, readwrite, retain) FBGraphObjectPagingLoader *loader;

// these properties are only used by unit tests, and should not be removed or made public
@property (nonatomic, readwrite, assign) BOOL hasCompletedFetch;
@property (nonatomic, readwrite, assign) BOOL usePageLimitOfOne;
- (void)setUsePageLimitOfOne;

@end

@implementation FBFriendPickerCacheDescriptor

@synthesize fieldsForRequest = _fieldsForRequest,
userID = _userID,
loader = _loader,
hasCompletedFetch = _hasCompletedFetch,
usePageLimitOfOne = _usePageLimitOfOne;

- (id)init {
return [self initWithUserID:nil
fieldsForRequest:nil];
}

- (id)initWithUserID:(NSString*)userID {
return [self initWithUserID:userID
fieldsForRequest:nil];
}

- (id)initWithFieldsForRequest:(NSSet*)fieldsForRequest {
return [self initWithUserID:nil
fieldsForRequest:fieldsForRequest];
}

- (id)initWithUserID:(NSString*)userID fieldsForRequest:(NSSet*)fieldsForRequest {
self = [super init];
if (self) {
self.fieldsForRequest = fieldsForRequest ? fieldsForRequest : [NSSet set];
self.userID = userID;
self.hasCompletedFetch = NO;
self.usePageLimitOfOne = NO;
}
return self;
}

- (void)dealloc {
self.fieldsForRequest = nil;
self.userID = nil;
self.loader = nil;
[super dealloc];
}

- (void)prefetchAndCacheForSession:(FBSession*)session {
// datasource has some field ownership, so we need one here
FBGraphObjectTableDataSource *datasource = [[FBGraphObjectTableDataSource alloc]
init];
datasource.groupByField = @"name";

// me or one of my friends that also uses the app
NSString *user = self.userID;
if (!user) {
user = @"me";
}

// create the request object that we will start with
FBRequest *request = [FBFriendPickerViewController requestWithUserID:user
fields:self.fieldsForRequest
dataSource:datasource
session:session];

// this property supports unit testing
if(self.usePageLimitOfOne) {
[request.parameters setObject:@"1"
forKey:@"limit"];
}

self.loader.delegate = nil;
self.loader = [[FBGraphObjectPagingLoader alloc] initWithDataSource:datasource];
self.loader.session = session;
[self.loader release];

self.loader.delegate = self;
self.loader.pagingMode = FBGraphObjectPagingModeImmediateViewless;

// make sure we are around to handle the delegate call
[self retain];

// seed the cache
[self.loader startLoadingWithRequest:request
cacheIdentity:FBFriendPickerCacheIdentity
skipRoundtripIfCached:NO];

[datasource release];
}

- (void)setUsePageLimitOfOne {
self.usePageLimitOfOne = YES;
}

- (void)pagingLoaderDidFinishLoading:(FBGraphObjectPagingLoader *)pagingLoader {
self.loader.delegate = nil;
self.loader = nil;
self.hasCompletedFetch = YES;

// this feels like suicide!
[self release];
}

@end
33 changes: 33 additions & 0 deletions src/FBFriendPickerViewController+Internal.h
@@ -0,0 +1,33 @@
/*
* Copyright 2012 Facebook
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#import <Foundation/Foundation.h>
#import "FBFriendPickerViewController.h"
#import "FBRequest.h"
#import "FBGraphObjectTableDataSource.h"
#import "FBSession.h"

// This is the cache identity used by both the view controller and cache descriptor objects
extern NSString *const FBFriendPickerCacheIdentity;

@interface FBFriendPickerViewController (Internal)

+ (FBRequest*)requestWithUserID:(NSString*)userID
fields:(NSSet*)fields
dataSource:(FBGraphObjectTableDataSource*)datasource
session:(FBSession*)session;

@end

0 comments on commit c01c758

Please sign in to comment.