Facebook IOS SDK trying to make singleton class? - iphone

Hy, i am trying to make from Facebook IOS SDK (Octomber 2011) a class of my own in where i can make all the methods and functions that i need and just import this class in any of my application view controllers and call it.
So this way i don't need to do all the initialization and delegation to the controllers in where i use the facebook.
So i want to do like this, [myfacebookclass initwithappID:myappid]
[myfacebookclass postmessage:#"some message"];
The thing is when i am seting authorizeWithFBAppAuth:YES safariAuth:YES flags in facebook.m ( the original class) and i do a postmessage it redirects me on Facebook Application or Safari and check's for permision, i hit ok and then redirects me in my application and doesn't post message.
WHen i am trying to post message i do like this :
This is in my own facebook class
myfacebookclass *facebook2;
+(void)initWithAppID:(NSString*) facebookAppId {
if (facebook2 == nil) {
facebook2 = [myfacebookclass new];
[facebook2 setWithAppId:facebookAppId];
}
}
- (void) postMessage1:(NSString *)messageToPost {
if ([self.facebook isSessionValid]) {
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
self.applicationID, #"api_key",
messageToPost, #"message",
nil];
[self.facebook requestWithGraphPath:#"me/feed" andParams:params andHttpMethod:#"POST" andDelegate:self];
} else {
NSArray * neededPermissions = [[[NSArray alloc] initWithObjects:#"user_about_me", #"publish_stream", nil] autorelease];
[self.facebook authorize:neededPermissions];
}
}
+ (void)postMessage:(NSString*) message {
[facebook2 postMessage1:message];
}
I also implemented:
(BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
return [facebook handleOpenURL:url];
}
i've didn't modified facebook.m or other classes in Facebook IOS SDK.

a good practice when making a singleton class is to use shared instance. Correct singleton also has to include some memory management overridden methods. In your case it can be done like this:
#implementation FacebookManager
static FacebookManager *mySharedFacebookManager;
+ (FacebookManager*)sharedFacebookManager {
#synchronized(self) {
if(mySharedFacebookManager == nil) {
mySharedFacebookManager = [[self alloc] init];
}
}
return mySharedFacebookManager;
}
+ (id)allocWithZone:(NSZone *)zone {
#synchronized(self) {
if(mySharedFacebookManager == nil) {
mySharedFacebookManager = [super allocWithZone:zone];
return mySharedFacebookManager;
}
}
return nil;
}
- (id)copyWithZone:(NSZone *)zone {
return self;
}
- (id)retain {
return self;
}
- (unsigned)retainCount {
return UINT_MAX;
}
- (oneway void)release {
}
- (id)autorelease {
return self;
}
In your case you may have Facebook type object as ivar, and some methods to wrap over FB API, for example like this:
- (id)init {
self = [super init];
if(self) {
facebook = [[Facebook alloc] initWithAppId:FB_APP_ID andDelegate:self];
// restore previous session
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
...
}
return self;
}
- (void)login {
NSArray *permissions = [NSArray arrayWithObjects: #"user_about_me", #"publish_stream", nil];
[facebook authorize:permissions];
}
- (void)postToFeed:(NSString*)messageToPost {
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
messageToPost, #"message",
nil];
[facebook requestWithGraphPath:#"me/feed"
andParams:params
andHttpMethod:#"POST"
andDelegate:self];
}
From other classes which have to deal with Facebook the construction is simple:
[[FacebookManager sharedFacebookManager] login];
...
[[FacebookManager sharedFacebookManager] postToFeed:#"Hello World!"];
I hope this snippets will help you.
To manage your facebook session you have to remember accessToken manually in FBSessionDelegate methods like that:
- (void)fbDidLogin {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
}
- (void)fbDidLogout {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults removeObjectForKey:#"FBAccessTokenKey"];
[defaults removeObjectForKey:#"FBExpirationDateKey"];
[defaults synchronize];
}

Related

Repeating authorization Window

I'm using Xcode 4.3.1
In my app I try to use Facebook SSO.My requirement is at the first time the app should ask for the authorization after that it should check whether the app is authorized by the user and should move to the next process(even after the task in the device is cancelled).I don't that authorization window to repeat again and again.
in Appdelegate:
facebook=[[Facebook alloc]initWithAppId:appid andDelegate:first];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSLog(#"%#Defaults:",[defaults objectForKey:#"FBAccessTokenKey"]);
if ([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"])
{
facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
accessToken=facebook.accessToken;
facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
date=facebook.expirationDate;
}
In my view Controller:
-(IBAction)LoginClick:(id)sender
{
NSUserDefaults *defaults1 = [NSUserDefaults standardUserDefaults];
[defaults1 setObject:xapp.facebook.accessToken forKey:#"FBAccessTokenKey"];
[defaults1 setObject:xapp.facebook.expirationDate forKey:#"FBExpirationDateKey"];
[defaults1 synchronize];
if (![xapp.facebook isSessionValid])
{
permissions = [[NSArray alloc] initWithObjects:#"read_stream",#"publish_stream", nil];
[xapp.facebook authorize:permissions];
}
else if([xapp.facebook isSessionValid])
{
NSLog(#"Hiii");
permissions=nil;
[xapp.facebook authorize: nil];
}
}
How can I make the authorization window to not appear after the app is authorized...
Alright, you are asking for permissions each time you run your app in your AppDelegate. To prevent this, you have to make a separate method for permission that will be granted only if the login button is pressed and checked if the app is permitted or not. Try this in your AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self.window makeKeyAndVisible];
facebook = [[Facebook alloc] initWithAppId:#"YOURAPPID" andDelegate:self];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"] && [defaults objectForKey:#"FBExpirationDateKey"])
{
facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
return YES;
}
Above your fbDidLogIn method in your AppDelegate add this method, you have to add the FBUser protocol to your AppDelegate:
-(void)fbLogin:(id<FBUser>)_listener
{
listener = _listener;
if(![facebook isSessionValid])
{
NSArray* permissions = [[NSArray arrayWithObjects:
#"publish_stream",
#"read_stream",
nil] retain];
[facebook authorize:permissions];
}
else
{
[listener facebookDidLogin];
}
}
And in your ViewController modify your login method like this:
-(IBAction)LoginClick:(id)sender
{
YourAppDelegate *appDelegate = (YourAppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate fbLogin:self];
}
The FBUser.h is a custom header file that defines the protocol method -(void)fbDidLogIn. This is just to make sure that, the app does not ask login permission each it time launches.
#import <Foundation/Foundation.h>
#protocol FBUser <NSObject>
-(void)facebookDidLogin;
#end
By this, the login method is only called when the app needs to login to Facebook and do something.
Hope this helps you. Cheers!

ios facebook api not fire fbLogin

i need to use the facebook api:
in the appdelegate.m I have this code:
// Initialize Facebook
facebook = [[Facebook alloc] initWithAppId:#"MY_TOKEN" andDelegate:self];
// Check and retrieve authorization information
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"] && [defaults objectForKey:#"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
after, in another view I have this:
AppDelegate* dlg = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSArray *permissions = [[NSArray alloc] initWithObjects:#"offline_access", nil];
if (![[dlg facebook] isSessionValid]) {
[[dlg facebook] authorize:permissions];
}
and works fine: call safari with the authorization to use my app, I click Ok to authorize and my app is called again... my app visualize the last view before the authorize, but the event
- (void)fbDidLogin
{
NSLog(#"fbDidLogin");
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
}
in AppDelegate.m (my appdelegate have FBSessionDelegate) is not fired (also the other events of FBSessionDelegate like fbDidNotLogin are not fired...
where is my error?
thanks in advance
I think you forgot about this two methods and perhaps forgot to add your Facebook app id to URL types in info file. for more detail
// Pre 4.2 support
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [facebook handleOpenURL:url];
}
// For 4.2+ support
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [facebook handleOpenURL:url];
}

Facebook API dialog page showing error in second time and after that

I want to share my app details.I just done as same given in facebook tutorial.When user loggen in and dialog page appears and i posted my msg.and it worked fine for first time only.when user tapped a button to share again,the dialog appears and showing error page
"Error occurred with 'Your_APP_NAME'.please try again later."
I followed the tutorial in the facebook link below here. https://developers.facebook.com/docs/mobile/ios/build/
Here it is my code.
-(void)buttonPressed:(id)sender{
facebook = [[Facebook alloc] initWithAppId:#"YOUR_APP_ID" andDelegate:self];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"] && [defaults objectForKey:#"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
if (![facebook isSessionValid]) {
[facebook authorize:nil];
}else{
[self postWall];
}
// Pre 4.2 support
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [facebook handleOpenURL:url];
}
- (void)fbDidLogin {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
[self postWall];
}
-(void)postWall{
NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
kAppId,#"app_id",
#"https://developers.facebook.com/docs/reference/dialogs/",#"link",
#"http://fbrell.com/f8.jpg",#"picture",
#"Facebook Dialogs",#"name",
#"Reference Documentation",#"caption",
#"Using Dialogs to interact with users.",#"description",
#"Facebook Dialogs are so easy!",#"message",
nil];
[[self facebook] dialog:#"feed" andParams:params andDelegate:self];
}
I do all this code in my viewcontroller file(Not in app delegate).I want to open facebook only when i press the button..So i put these codings in my buttonpressed method.
Try with removing
kAppId,#"app_id"
from your NSMutableDictionary params

How to make my method run when the view re-load

I want to create a login button. When I click it the facebook launches, I accept my application, the Facebook application closes and my application reloads. My problem is that the second time my application starts, after accepting on Facebook, I cannot find where to disable the login button.
I wrote this code:
-(IBAction) login:(id)sender;
{
AutoAppDelegate *delegate = (AutoAppDelegate *) [[UIApplication sharedApplication] delegate];
// Check and retrieve authorization information
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"]) {
[delegate facebook].accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
[delegate facebook].expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
if (![[delegate facebook] isSessionValid]) {
[delegate facebook].sessionDelegate = self;
NSArray *permissions = [[NSArray alloc] initWithObjects:
#"user_likes",
#"read_stream",
nil];
[[delegate facebook] authorize:permissions];
} else {
logIn.hidden=YES;
lbl.text=#"";
lbl.text=#"Connected";
[self showLoggedIn];
}
}
- (void) showLoggedIn {
NSLog(#"11 Logged In ");
lbl.text=#"";
lbl.text=#"Connected";
}
- (void) showLoggedOut {
NSLog(#"11 Not Logged In ");
lbl.text=#"";
lbl.text=#"Not Connected";
}
- (void) viewWillAppear:(BOOL)animated
{
//[self.navigationController setNavigationBarHidden:YES animated:animated];
[super viewWillAppear:animated];
AutoAppDelegate *delegate = (AutoAppDelegate *) [[UIApplication sharedApplication] delegate];
// Check and retrieve authorization information
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"]) {
[delegate facebook].accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
[delegate facebook].expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
if (![[delegate facebook] isSessionValid]) {
// [self showLoggedOut];
NSLog(#"Not Connected");
} else {
// [self showLoggedIn];
NSLog(#"Connected");
}
}
The viewWillAppear works the first time, but when I give permissions in the Facebook application, my application restarts but not viewWillAppear method!
You need to put the code in your application delegate (applicationWillEnterForeground), as it's the only thing to get notified automatically when the app is re-opened (your view is not necessarily re-drawn).
Have you tried to calling setNeedsDisplay on the view after the Facebook thing is done?

why fbdidlogin didn't call?

- (id)init {
if (self == [super init]) {
facebook = [[Facebook alloc] initWithAppId:kAppId];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
if (![facebook isSessionValid]) {
permissions = [[NSArray arrayWithObjects:
#"read_stream", #"user_birthday",
#"publish_stream", nil] retain];
[facebook authorize:permissions delegate:self];
}
[self login];
}
return self;
}
- (void)login {
if (![_session isConnected]) {
[self postToWall];
}
if (![facebook isSessionValid]) {
[facebook authorize:permissions delegate:self];
}
}
- (void)fbdidLogin {
[[NSUserDefaults standardUserDefaults] setObject:self.facebook.accessToken forKey:#"FBAccessToken"];
[[NSUserDefaults standardUserDefaults] setObject:self.facebook.expirationDate forKey:#"FBExpirationDate"];
// User has logged in to Facebook, now get their userId from Facebook
[facebook requestWithGraphPath:#"me" andDelegate:self];
}
-(void)postToWall
{
SBJSON *jsonWriter = [[SBJSON new] autorelease];
NSDictionary *actionLinks = [NSArray arrayWithObjects:[NSDictionary dictionaryWithObjectsAndKeys:
#"Always Running",#"text",#"http://itsti.me/",#"href", nil], nil];
NSString *actionLinksStr = [jsonWriter stringWithObject:actionLinks];
NSDictionary *attachment = [NSDictionary dictionaryWithObjectsAndKeys:
#"Your Happiness!", #"name",
#"asda", #"caption",
#"asdf", #"description",
nil];
NSString *attachmentStr = [jsonWriter stringWithObject:attachment];
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
#"Share on Facebook", #"user_message_prompt",
actionLinksStr, #"action_links",
attachmentStr, #"attachment",
nil];
[facebook dialog:#"stream.publish" andParams:params andDelegate:self];
}
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [facebook handleOpenURL:url];
}
This is my methods for calling facebook dialog boxes.But every time when i click to score for publishing;The permission box came first.I need to give permission after that the publish dialog box comes.I want to give permission ones and i want it to save it;after saving it i don't wanna see the permission box ever again.How can i do it?What is wrong with my code?
edit:
My access token and expiration date is null i guess thats because of this.
A few things to check, you call the method login handling method "fbdidLogin" instead of fbDidLogin. This is case sensitive.
Make sure in your view controller header file that you added FBSessionDelegate as one of the protocols you support. That could be a reason fbDidLogin is not called. You could always add an NSLog to verify that the fbDidLogin method is reached.
You need to implement Facebook's Single-Sign-On feature.
http://developers.facebook.com/docs/guides/mobile/#ios
This link has the step-by-step guide for implementing SSO, if you follow it carefully your App will request for permission once, then it will never request permission again (until the user remove your App)
Note that, you will need to go to www.facebook.com and use the "Developer Tools" to create a new Facebook App, you will be the admin of the app, and you will have your AppID, you will need this too.