Post Photo Facebook iOS - ios

I'm trying to upload a photo to Facebook. I read a lot of tutorials and examples and still can't get it to work. Many times I get an EXC_BAD_ACCESS in this line:
[_facebook requestWithGraphPath:#"me/photos"
andParams:photosParams
andHttpMethod:#"POST"
andDelegate:self];
Other times nothing appears. I want the user to login only when they click on "share image" in Facebook. Thats why I didn't put the delegate in the appDelegate. Below is my code:
if (_facebook != nil) {
[self fbDidLogin];
}
_publishedImage = img;
_facebook = [[Facebook alloc] initWithAppId:#"235694579858240" 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])
{
NSArray* permissions = [[NSArray alloc] initWithObjects:
#"offline_access", #"publish_stream", #"publish_actions", #"photo_upload", nil];
[_facebook authorize:permissions];
}
UIImage *imgSource = img;
NSString *strMessage = #"This is the photo caption";
NSMutableDictionary* photosParams = [NSMutableDictionary dictionaryWithObjectsAndKeys:
imgSource,#"source",
strMessage,#"message",
nil];
[_facebook requestWithGraphPath:#"me/photos"
andParams:photosParams
andHttpMethod:#"POST"
andDelegate:self];
My ViewController has these delegates:
<UIImagePickerControllerDelegate, UIActionSheetDelegate, UIGestureRecognizerDelegate, MFMailComposeViewControllerDelegate, FBSessionDelegate, FBDialogDelegate, FBRequestDelegate>
Edit: Are there any plugins to share photos easily in Facebook, G+, and everything else easily?

Instead of using the graph why don't you try:
if ([fbAppDelegate.facebook isSessionValid]) {
NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys: #"http://hd.ipad-wallpapers.fr/thumbs/wooden_apple_logo_4-t1.jpg // but could also use UIImage", #"picture", nil]; // you don't
[fbAppDelegate.facebook dialog:#"feed" andParams:params andDelegate:self];
}
// this is what I do .....

Related

NSUserDefaults and alertView

I am creating a Disclaimer that will be shown when the user first launches the app. The disclaimer is an alertView with 2 option. If user agrees then firstViewController will display. If he doesn't he will be redirected to another viewController. But I can't get the disclaimer to disappear if the user agrees the first time. It is shown every time the app launches. Any help would be appreciated. Thank you in advance..
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (![[defaults valueForKey:#"keyDisclaimer"] isEqualToString:#"accepted"]) {
UIAlertView *disclaimer = [[UIAlertView alloc] initWithTitle:#"Read Before use" message:#"By using this app you agree to its terms and conditions.\n\n\n\n\n\n\n\n\n\n\ntext heren\n\n\n\n\n\n\n\n\n\n\n\n\n" delegate:self cancelButtonTitle:#"No!" otherButtonTitles:#"Yes Let me In", nil];
[disclaimer show];
}
// Override point for customization after application launch.
return YES;
}
-(void) alertView:(UIAlertView *) alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
NSString *buttonString = {[alertView buttonTitleAtIndex:buttonIndex]};
if ([buttonString isEqualToString:#"Yes Let me In"]) {
NSMutableDictionary* defaultValues = [NSMutableDictionary dictionary];
[defaultValues setValue:#"accepted"forKey:#"keyDisclaimer"];
[[NSUserDefaults standardUserDefaults] registerDefaults:defaultValues];
}
else if ([buttonString isEqualToString:#"No!"]) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Sorry!" message:#"You are not allowed to use this app due to the fact that you did not agree to the terms and Conditions. Please exit this app!" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
// [[NSUserDefaults standardUserDefaults] setValue:#"notAccepted" forKey:#"keyDisclaimer"];
}
if ([buttonString isEqualToString:#"OK"]) {
introViewController *intro = [[introViewController alloc] initWithNibName:#"introViewController" bundle:nil];
_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
_window.rootViewController = intro;
[_window makeKeyAndVisible];
}
}
NSMutableDictionary* defaultValues = [NSMutableDictionary dictionary];
[defaultValues setValue:...forKey:...]
[[NSUserDefaults standardUserDefaults] registerDefaults:defaultValues];
This will register your defaults if they are not set (for the first time)
Also, seems like you're forgetting [defaults synchronize] to commit changes after setting values. If so, you don't need the registerDefaults method at all.
Like this:
if ([buttonString isEqualToString:#"Yes Let me In"]) {
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
[defaults setValue:#"accepted"forKey:#"keyDisclaimer"];
[defaults synchronize];
}
You want to use something like stringForKey or objectForKey instead of valueForKey.
if([[defaults stringForKey:#"keyDisclaimer"] isEqualToString:#"accepted"]) {
I've had bad experiences with valueForKey in the past not always working the way I want. That might be what's causing you some problems.

Facebook ios logout method does not work

I have used this method for logout facebook in app
- (void)fbDidLogout {
// Remove saved authorization information if it exists
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]) {
[defaults removeObjectForKey:#"FBAccessTokenKey"];
[defaults removeObjectForKey:#"FBExpirationDateKey"];
[defaults synchronize];
}
NSLog(#"logout success!");
}
This method has been invoked, but when I relaunch app the facebook still know about my latest authorization.
My full implementation
I create singleton object for facebook instance.
this is my manager .h
#import <Foundation/Foundation.h>
#import "FBConnect.h"
#interface FacebookManager : NSObject <FBSessionDelegate> {
Facebook *facebook;
}
#property (nonatomic, strong) Facebook *facebook;
+ (FacebookManager *)sharedInstance;
- (void)initWithAppID:(NSString *)appID;
#end
this is singleton facebookmanager .m
#import "FacebookManager.h"
#implementation FacebookManager
#synthesize facebook;
static FacebookManager *_sharedInstance = nil;
+ (FacebookManager *)sharedInstance {
#synchronized(self) {
if (!_sharedInstance) {
_sharedInstance = [[FacebookManager alloc] init];
}
}
return _sharedInstance;
}
- (void)initWithAppID:(NSString *)appID {
facebook = [[Facebook alloc] initWithAppId:appID 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];
}
}
- (void)fbDidLogout {
// Remove saved authorization information if it exists
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]) {
[defaults removeObjectForKey:#"FBAccessTokenKey"];
[defaults removeObjectForKey:#"FBExpirationDateKey"];
[defaults synchronize];
}
NSLog(#"logout success!");
}
#end
in appDelegate I make next:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
fbManager = [FacebookManager sharedInstance];
[fbManager initWithAppID:#"myappid"];
... (some other code)
}
also add this code to app delegate:
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [fbManager.facebook handleOpenURL:url];
}
- (void)fbDidLogin {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[fbManager.facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[fbManager.facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
}
In other view controller I call this method for logout:
- (IBAction)logoutFacebook:(id)sender {
FacebookManager *fbManager = [FacebookManager sharedInstance];
[fbManager.facebook logout];
}
also in plist I have add needed url scheme.
Modify the Facebook.m code to this, which works for me.
-(void)logout:(id)delegate {
self.sessionDelegate = delegate;
[_accessToken release];
_accessToken = nil;
[_expirationDate release];
_expirationDate = nil;
NSHTTPCookieStorage *cookies = [NSHTTPCookieStorage sharedHTTPCookieStorage];
NSArray *facebookCookies = [cookies cookiesForURL:[NSURL URLWithString:#"http://login.facebook.com"]];
for (NSHTTPCookie* cookie in facebookCookies){
[cookies deleteCookie:cookie];
}
//Adds this one.
for (NSHTTPCookie *_cookie in cookies.cookies){
NSRange domainRange = [[_cookie domain] rangeOfString:#"facebook"];
if(domainRange.length > 0){
[cookies deleteCookie:_cookie];
}
}
if ([self.sessionDelegate respondsToSelector:#selector(fbDidLogout)]){
[_sessionDelegate fbDidLogout];
}
}
What do you mean by "when I relaunch app the facebook still know about my latest authorization" ? Does this mean your FB accesstoken is still valid? You still see the userdefaults values? What exactly?
If you mean that when you trigger the FB login again, it automatically logs you in again, then yes if you have the Facebook APP installed in iOS, the user will have to logout from the FB app manually to switch an account.
If the FB app is not installed, then yes the SSO should prompt the user to login again after initiating a logout.
That seems to be the way the ios sdk api with sso/oauth 2.0 works. I have not been able to logout completely even after clearing the tokens and I have not been able to switch users from the App. Got to go to the FB app to switch users
As a workaround, change the line in Facebook.m and disable the safariAuth
// [self authorizeWithFBAppAuth:YES safariAuth:YES];
[self authorizeWithFBAppAuth:NO safariAuth:NO]
But then you have to type in the username and password everytime you authorize.
In Facebook.m, add the following code to remove cookies at m.facebook.com domain.
- (void)invalidateSession {
...
NSArray* facebookMCookies = [cookies cookiesForURL:
[NSURL URLWithString:#"https://m.facebook.com"]];
for (NSHTTPCookie* cookie in facebookMCookies) {
[cookies deleteCookie:cookie];
}
...
}
I have tried with success this code:
NSFileManager *fm = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cachesDirectory = [paths objectAtIndex:0];
NSLog(#"cache dir %#", cachesDirectory);
NSError *error = nil;
for (NSString *file in [fm contentsOfDirectoryAtPath:cachesDirectory error:&error]) {
BOOL success = [fm removeItemAtPath:[NSString stringWithFormat:#"%#/%#", cachesDirectory, file] error:&error];
if (!success || error) {
NSLog(#"Error delete file: %#, %#", file, error);
} else {
NSLog(#"Deleted file: %#", file);
}
}

I couldn't get a Facebook access token to use the graph API on iOS

I am a newbie for StackOverflow and iOS. I am trying get user informations like groups, books etc. and I need use the Facebook graph API for that. To use graph API you must use an access token. I read article on the Facebook developer page about this topic and I wrote some code, but it didn't work. Can you help me? Is my code right or shall I use another way?
my .h file:
#import <UIKit/UIKit.h>
#import "FBConnect.h"
#interface FirstViewController : UIViewController <FBSessionDelegate,FBLoginDialogDelegate,FBRequestDelegate>{
Facebook *face;
}
#property(nonatomic,retain)Facebook *face;
-(IBAction)facePushed:(id)sender;
-(IBAction)logoutPushed:(id)sender;
my .m file:
-(IBAction)facePushed:(id)sender{
NSLog(#"FacePushed Began");
face=[[Facebook alloc]initWithAppId:#"313714785358239" andDelegate:self];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"]) {
face.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
face.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
if (![face isSessionValid]) {
[face authorize:nil ];
}
else {
NSLog(#"Session is valid");
}
NSLog(#"FacePushed End");
}
}
- (void)fbDidLogin {
NSLog(#"aslan");
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[face accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[face expirationDate] forKey:#"FBExpirationDateKey"];
NSLog(#"%#", [face accessToken]);
[defaults synchronize];
}
- (void)fbDialogLogin:(NSString *)token expirationDate:(NSDate *)expirationDate {
NSLog(#"%#",token);
}
you have to check the following in your implementation :
you need to get a permissions before you authorize your app
if (![face isSessionValid])
{
NSArray *permissions = [[NSArray alloc] initWithObjects:
#"user_likes",
#"read_stream",
#"publish_stream",
nil];
[face authorize:permissions];
[permissions release];
}
you need to add the following functions in your application delegate(the facebook object here is your instance value of FaceBook Class).
// 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];
}
in your info.plist add to URL types > URL Schemes > your facebok app ID with fb prefix (finally your value will be like this fb313714785358239).
Good Luck.

Using Facebook Graph API on iOS

This is my first post on StackOverflow but i use this for a long time...
My problem is basically simple, I want to share the content of a UITextView(mShareText) on the user's wall without prompting any Dialog. Basically, the user has to fill its message on the UITextView and then click on a "post" UIButton. Simple isn't it ?
I've downloaded the Facebook iOS SDK and copied it into my project. I've included "FBConnect.h" and "Facebook.h" on my controller's header file and created a var : Facebook* facebook;, the controller also implements the following delegates : FBSessionDelegate, FBRequestDelegate.
On my controller's implementation file, I've a IBAction triggered when the user clicks on the "post" UIButton.
- (IBAction)onShareByFBPressed:(id)sender {
NSLog(#"onShareByFBPressed");
// Facebook settings
NSMutableDictionary* params = [[NSMutableDictionary alloc] initWithCapacity:3];
[params setObject:mShareText.text forKey:#"message"];
[params setObject:#"http://www.example.com" forKey:#"link"];
[params setObject:#"https://www.example.com/myImg.jpg" forKey:#"picture"];
[facebook requestWithGraphPath:#"me/feed"
andParams:params
andHttpMethod:#"POST"
andDelegate:self];
[params release];
}
I've implemented this on my viewdidload:
- (void)viewDidLoad
{
NSLog(#"viewDidLoad");
[super viewDidLoad];
(...)
// Test facebook
facebook = [[Facebook alloc] initWithAppId:#"XXXXXXXXXXX" andDelegate:self];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"] && [defaults objectForKey:#"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
NSLog(#"AccessToken: %# ExpirationDate: %#", facebook.accessToken, facebook.expirationDate);
}else{
NSLog(#"No AccessToken or ExpirationDate");
}
if (![facebook isSessionValid]) {
[facebook authorize:[NSArray arrayWithObjects:#"publish_stream", nil]];
}
}
Here are different methods I had to implement due to the delegates :
// 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];
}
- (void)fbDidLogin {
NSLog(#"fbDidLogin");
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
}
- (void)fbSessionInvalidated{
NSLog(#"fbSessionInvalidated");
}
- (void)fbDidLogout{
NSLog(#"fbDidLogout");
}
- (void)fbDidExtendToken:(NSString*)accessToken expiresAt:(NSDate*)expiresAt{
NSLog(#"fbDidExtendToken");
}
- (void)fbDidNotLogin:(BOOL)cancelled{
NSLog(#"fbDidNotLogin");
}
- (void)request:(FBRequest *)request didReceiveResponse:(NSURLResponse *)response{
NSLog(#"didReceiveResponse: %#", response);
}
- (void)request:(FBRequest *)request didFailWithError:(NSError *)error{
NSLog(#"didFailWithError: %#", [error description]);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Share on Facebook"
message:#"An error occured"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}
Unfortunatelly, everytime I try to trigger my "onShareByFBPressed" method, I got the following error on the log:
2012-02-17 13:02:06.401 Mixtapes[935:707] didFailWithError: Error Domain=facebookErrDomain Code=10000 "The operation couldn’t be completed. (facebookErrDomain error 10000.)" UserInfo=0x1f6f60 {error=<CFBasicHash 0x1f6660 [0x3ec6d630]>{type = mutable dict, count = 3,
entries =>
2 : <CFString 0x1f64a0 [0x3ec6d630]>{contents = "type"} = <CFString 0x1f6b10 [0x3ec6d630]>{contents = "OAuthException"}
3 : <CFString 0x1f6ab0 [0x3ec6d630]>{contents = "message"} = <CFString 0x1f6a10 [0x3ec6d630]>{contents = "An active access token must be used to query information about the current user."}
6 : <CFString 0x1f6e60 [0x3ec6d630]>{contents = "code"} = 2500
}
}
Can anyone tell me what's wrong with my implementation ??
Thanks a lot.
Best regards.
EDIT:
#Adil
Thanks for your proposal. It actually works somethimes.
Sometimes i got the following error :
didFailWithError: Error Domain=facebookErrDomain Code=10000 "The operation couldn’t be completed. (facebookErrDomain error 10000.)" UserInfo=0xa17e0d0 {error=<CFBasicHash 0xa171e10 [0x3ec6d630]>{type = mutable dict, count = 3,
entries =>
2 : <CFString 0xa179d10 [0x3ec6d630]>{contents = "type"} = <CFString 0xa17a280 [0x3ec6d630]>{contents = "OAuthException"}
3 : <CFString 0x6127710 [0x3ec6d630]>{contents = "message"} = <CFString 0xa178db0 [0x3ec6d630]>{contents = "Error validating access token: Session is invalid. This could be because the application was uninstalled after the session was created."}
6 : <CFString 0xa17e020 [0x3ec6d630]>{contents = "code"} = 190
}
}
Thanks for your help
The problem here is:
The facebook which is authororized is AppDelegate's facebook object, not your ViewController's facebook.
Solution:
Instead allocating new Facebook object for every ViewController or where you needed.
you should make a property of your application delegate. like this:
in appDelegate.h
#property(nonatomic, retain) Facebook *facebook;
and synthesize it in appDelegate.m and now put initialization of Facebook in
- (BOOL)application:(UIApplication *)ap didFinishLaunchingWithOptions:(NSDictionary *)op
{
// other code....
facebook = [[Facebook alloc] initWithAppId:#"XXXXXXXXXXX" andDelegate:self];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"] && [defaults objectForKey:#"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
NSLog(#"AccessToken: %# ExpirationDate: %#", facebook.accessToken, facebook.expirationDate);
}else{
NSLog(#"No AccessToken or ExpirationDate");
}
return true;
}
now where do you want to use it, write something like this:
- (void)viewDidLoad
{
[super viewDidLoad];
//...
AppDelegate *app = (AppDelegate *)[[UIApplication sharedApplication] delegate];
facebook = app.facebook;
if (![facebook isSessionValid]) {
[facebook authorize:[NSArray arrayWithObjects:#"publish_stream", nil]];
}
}
Try to deauthorize your application and then authorize it again

Problems with alloc and facebook init

I have a singleton class that i use to handle all the facebook stuff...
but when i try to init the _facebook it throws an unrecognizer selector exception
(id)initWithAppId:(NSString *)appId andDelegate:(id)delegate;
this is the init method i'm using...
-(void) login {
// Check if there is a valid session.
#try {
_facebook = [[Facebook alloc] initWithAppId:kAppId andDelegate:self];
}
#catch (NSException *exception) {
NSLog([NSString stringWithFormat:#"%#\n, %#", exception.name, exception.reason]);
}
#finally {
}
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:_permissions];
}else{
[_facebook requestWithGraphPath:#"me" andDelegate:self];
}
}
Try product -> clean. You have probably copied and replaced the Facebook source files outside XCode.

Resources