Skip to content

Commit

Permalink
Chapter6: update code for requesting friends facebook profile picture…
Browse files Browse the repository at this point in the history
…s. add facebook requests to a queue
  • Loading branch information
mrchristopher124 committed May 13, 2011
1 parent c37e409 commit 3f4522b
Show file tree
Hide file tree
Showing 8 changed files with 275 additions and 9 deletions.
12 changes: 12 additions & 0 deletions Chapter6/ApiFacebook/ApiFacebook.xcodeproj/project.pbxproj
Expand Up @@ -31,6 +31,8 @@
E1AEBA751311FEE300E1790D /* FBDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = E1AEBA6A1311FEE300E1790D /* FBDialog.m */; };
E1AEBAAC1311FF1000E1790D /* FBLoginButton.m in Sources */ = {isa = PBXBuildFile; fileRef = E1AEBAAB1311FF1000E1790D /* FBLoginButton.m */; };
E1AEBACB1311FF4100E1790D /* FBConnect.bundle in Resources */ = {isa = PBXBuildFile; fileRef = E1AEBACA1311FF4100E1790D /* FBConnect.bundle */; };
E1AF0FBC137B931A003E40CE /* NSMutableArray+QueueAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = E1AF0FBB137B931A003E40CE /* NSMutableArray+QueueAdditions.m */; };
E1AF0FBF137B9D29003E40CE /* FacebookRequestController.m in Sources */ = {isa = PBXBuildFile; fileRef = E1AF0FBE137B9D29003E40CE /* FacebookRequestController.m */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand Down Expand Up @@ -81,6 +83,10 @@
E1AEBAAA1311FF1000E1790D /* FBLoginButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FBLoginButton.h; path = "../../../facebook-ios-sdk/sample/DemoApp/Classes/FBLoginButton.h"; sourceTree = "<group>"; };
E1AEBAAB1311FF1000E1790D /* FBLoginButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FBLoginButton.m; path = "../../../facebook-ios-sdk/sample/DemoApp/Classes/FBLoginButton.m"; sourceTree = "<group>"; };
E1AEBACA1311FF4100E1790D /* FBConnect.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = FBConnect.bundle; path = "../../../facebook-ios-sdk/sample/FBConnect.bundle"; sourceTree = "<group>"; };
E1AF0FBA137B931A003E40CE /* NSMutableArray+QueueAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableArray+QueueAdditions.h"; sourceTree = "<group>"; };
E1AF0FBB137B931A003E40CE /* NSMutableArray+QueueAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableArray+QueueAdditions.m"; sourceTree = "<group>"; };
E1AF0FBD137B9D29003E40CE /* FacebookRequestController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FacebookRequestController.h; sourceTree = "<group>"; };
E1AF0FBE137B9D29003E40CE /* FacebookRequestController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FacebookRequestController.m; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -114,6 +120,10 @@
E1AEBA131311FE2600E1790D /* MainView.m */,
E1AEBA141311FE2600E1790D /* MainViewController.h */,
E1AEBA151311FE2600E1790D /* MainViewController.m */,
E1AF0FBA137B931A003E40CE /* NSMutableArray+QueueAdditions.h */,
E1AF0FBB137B931A003E40CE /* NSMutableArray+QueueAdditions.m */,
E1AF0FBD137B9D29003E40CE /* FacebookRequestController.h */,
E1AF0FBE137B9D29003E40CE /* FacebookRequestController.m */,
);
path = Classes;
sourceTree = "<group>";
Expand Down Expand Up @@ -296,6 +306,8 @@
E1AEBA741311FEE300E1790D /* FBLoginDialog.m in Sources */,
E1AEBA751311FEE300E1790D /* FBDialog.m in Sources */,
E1AEBAAC1311FF1000E1790D /* FBLoginButton.m in Sources */,
E1AF0FBC137B931A003E40CE /* NSMutableArray+QueueAdditions.m in Sources */,
E1AF0FBF137B9D29003E40CE /* FacebookRequestController.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
23 changes: 23 additions & 0 deletions Chapter6/ApiFacebook/Classes/FacebookRequestController.h
@@ -0,0 +1,23 @@
//
// FacebookRequestController.h
// ApiFacebook
//
// Created by Christopher White on 5/12/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//

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

@interface FacebookRequestController : NSObject <FBRequestDelegate> {
NSDictionary *currentRequestDictionary;
NSMutableArray *requestQueue;
BOOL handlingRequest;
}

@property(nonatomic, retain) NSDictionary *currentRequestDictionary;

+ (FacebookRequestController*)sharedRequestController;
- (void)enqueueRequestWithGraphPath:(NSString*)path;

@end
147 changes: 147 additions & 0 deletions Chapter6/ApiFacebook/Classes/FacebookRequestController.m
@@ -0,0 +1,147 @@
//
// FacebookRequestController.m
// ApiFacebook
//
// Created by Christopher White on 5/12/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "FacebookRequestController.h"
#import "NSMutableArray+QueueAdditions.h"
#import "AppDelegate.h"

static FacebookRequestController *sharedRequestController;

@implementation FacebookRequestController

@synthesize currentRequestDictionary;

+ (FacebookRequestController*)sharedRequestController
{
if (nil == sharedRequestController) {
sharedRequestController = [[FacebookRequestController alloc] init];
}

return sharedRequestController;
}

- (void)dealloc
{
[currentRequestDictionary release];

[requestQueue release];

[super dealloc];
}

//do one request at a time...monitor the queue on a separate thread...
//check the queue on a separate thread and if the queue is not empty, then take the next one off of the queue and issue a request for it on the main thread

- (void)issueRequest:(NSString*)path
{
[facebook requestWithGraphPath:path andDelegate:self];
}

- (void)dequeueNextRequest
{
//only want to dequeue the next request if we're not currently processing a request

NSString *currentPath = nil;

if (NO == handlingRequest) {
@synchronized(self) {
if (0 < [requestQueue count]) {
currentPath = [requestQueue dequeue];
}
}

if (currentPath) {
handlingRequest = YES;
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
[dictionary setObject:currentPath forKey:@"path"];

self.currentRequestDictionary = dictionary;

[self performSelectorOnMainThread:@selector(issueRequest:) withObject:currentPath waitUntilDone:NO];
}
}
}

- (void)processQueue:(id)object
{
while (TRUE) {
[[FacebookRequestController sharedRequestController] dequeueNextRequest];

[NSThread sleepForTimeInterval:.01];
}
}

- (void)enqueueRequestWithGraphPath:(NSString*)path
{
if (nil == requestQueue) {
requestQueue = [[NSMutableArray array] retain];

[self performSelectorInBackground:@selector(processQueue:) withObject:nil];
}

@synchronized(self) {
[requestQueue enqueue:path];
}
}

#pragma mark -
#pragma mark FBRequestDelegate

- (void)requestLoading:(FBRequest *)request {
NSLog(@"requestLoading:");
}

/**
* Called when the server responds and begins to send back data.
*/
- (void)request:(FBRequest *)request didReceiveResponse:(NSURLResponse *)response {
NSLog(@"didReceiveResponse:");
}

/**
* Called when an error prevents the request from completing successfully.
*/
- (void)request:(FBRequest *)request didFailWithError:(NSError *)error {
NSLog(@"didFailWithError:");

handlingRequest = NO;
}

/**
* Called when a request returns and its response has been parsed into an object.
*
* The resulting object may be a dictionary, an array, a string, or a number, depending
* on thee format of the API response.
*/
- (void)request:(FBRequest *)request didLoad:(id)result {
NSLog(@"didLoad:");

//post a notification with the current dictionary
//issue notification to whoever registered for the given path and include the result response

handlingRequest = NO;

NSDictionary *userInfoDictionary = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:result, nil] forKeys:[NSArray arrayWithObjects:@"result", nil]];

NSString *path = [self.currentRequestDictionary objectForKey:@"path"];
[[NSNotificationCenter defaultCenter] postNotificationName:path
object:self
userInfo:userInfoDictionary];
}

/**
* Called when a request returns a response.
*
* The result object is the raw response from the server of type NSData
*/
- (void)request:(FBRequest *)request didLoadRawResponse:(NSData *)data {
NSLog(@"didLoadRawResponse:");
}


@end
28 changes: 26 additions & 2 deletions Chapter6/ApiFacebook/Classes/FriendTableViewCell.m
Expand Up @@ -8,6 +8,7 @@

#import "FriendTableViewCell.h"
#import "AppDelegate.h"
#import "FacebookRequestController.h"

@implementation FriendTableViewCell

Expand All @@ -22,13 +23,34 @@ - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reus
return self;
}

- (void)facebookRequestDidComplete:(NSNotification*)notification {

[[NSNotificationCenter defaultCenter] removeObserver:self];

UIImage *image = [UIImage imageWithData:(NSData*)[notification.userInfo objectForKey:@"result"]];
self.imageView.image = image;
[self setNeedsLayout];
}

- (void)setData:(NSDictionary *)dictionary {
[data release];
data = [dictionary retain];

self.textLabel.text = [data objectForKey:@"name"];

[facebook requestWithGraphPath:[NSString stringWithFormat:@"%@/picture", [data objectForKey:@"id"]] andDelegate:self];

self.imageView.image = nil;
[self setNeedsLayout];

[[NSNotificationCenter defaultCenter] removeObserver:self];

NSString *path = [NSString stringWithFormat:@"%@/picture", [data objectForKey:@"id"]];
[[FacebookRequestController sharedRequestController] enqueueRequestWithGraphPath:path];

//listen for a notification with the name of the identifier
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(facebookRequestDidComplete:)
name:path
object:nil];
}

- (void)requestLoading:(FBRequest *)request {
Expand Down Expand Up @@ -81,6 +103,8 @@ - (void)setSelected:(BOOL)selected animated:(BOOL)animated {


- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];

[data release];
[super dealloc];
}
Expand Down
2 changes: 1 addition & 1 deletion Chapter6/ApiFacebook/Classes/FriendsViewController.h
Expand Up @@ -9,7 +9,7 @@
#import <UIKit/UIKit.h>
#import "FacebookViewController.h"

@interface FriendsViewController : FacebookViewController <FBRequestDelegate> {
@interface FriendsViewController : FacebookViewController {
}

@end
24 changes: 18 additions & 6 deletions Chapter6/ApiFacebook/Classes/FriendsViewController.m
Expand Up @@ -9,6 +9,7 @@
#import "FriendsViewController.h"
#import "AppDelegate.h"
#import "FriendTableViewCell.h"
#import "FacebookRequestController.h"

@implementation FriendsViewController

Expand All @@ -23,14 +24,25 @@ - (id)init {
return self;
}

- (void)facebookRequestDidComplete:(NSNotification*)notification {

[[NSNotificationCenter defaultCenter] removeObserver:self];

[items release];
items = [[(NSDictionary*)[notification.userInfo objectForKey:@"result"] objectForKey:@"data"] retain];
[self.tableView reloadData];
}

- (void)viewDidLoad {
[super viewDidLoad];

// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;

//[facebook requestWithGraphPath:@"me?metadata=1" andDelegate:self];
[facebook requestWithGraphPath:@"me/friends" andDelegate:self];

[[FacebookRequestController sharedRequestController] enqueueRequestWithGraphPath:@"me/friends"];

//listen for a notification with the name of the identifier
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(facebookRequestDidComplete:)
name:@"me/friends"
object:nil];
}

/*
Expand Down
16 changes: 16 additions & 0 deletions Chapter6/ApiFacebook/Classes/NSMutableArray+QueueAdditions.h
@@ -0,0 +1,16 @@
//
// NSMutableArray+QueueAdditions.h
// ApiFacebook
//
// Created by Christopher White on 5/12/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import <Foundation/Foundation.h>


@interface NSMutableArray (QueueAdditions)
- (id) dequeue;
- (void) enqueue:(id)obj;
@end

32 changes: 32 additions & 0 deletions Chapter6/ApiFacebook/Classes/NSMutableArray+QueueAdditions.m
@@ -0,0 +1,32 @@
//
// NSMutableArray+QueueAdditions.m
// ApiFacebook
//
// Created by Christopher White on 5/12/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "NSMutableArray+QueueAdditions.h"


@implementation NSMutableArray (QueueAdditions)

- (id)dequeue
{
if ([self count] == 0) {
return nil;
}
id queueObject = [[[self objectAtIndex:0] retain] autorelease];
[self removeObjectAtIndex:0];
return queueObject;
}


// Add to the tail of the queue (no one likes it when people cut in line!)
- (void) enqueue:(id)anObject
{
[self addObject:anObject];
//this method automatically adds to the end of the array
}
@end

0 comments on commit 3f4522b

Please sign in to comment.