When I run below code with iOS 6.0, Its working
ACAccountStore *account = [[ACAccountStore alloc] init];
ACAccountType *accountType = [account accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[account requestAccessToAccountsWithType:accountType options:nil
completion:^(BOOL granted, NSError *error)
{
dispatch_async(dispatch_get_main_queue(), ^{
if (granted)
{
//MY CODE
}
});
}];
and When I run this code with iOS 5.0 or 5.1, It crashes with following output,
*** Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '-[ACAccountStore requestAccessToAccountsWithType:options:completion:]:
unrecognized selector sent to instance 0x68a57c0'
Don't know about this weird crash log..
Please tell me, How to get rid of this..
Use below method:
[account requestAccessToAccountsWithType:accountType withCompletionHandler:^(BOOL granted, NSError *error)
{
if (granted) {
//Your code
}
}
}];
This is a bit late, but the reason you're getting that error is that requestAccessToAccountsWithType:options:completion: is new in iOS 6.
In iOS 5 and earlier use the requestAccessToAccountsWithType:withCompletionHandler method instead (this method is deprecated in iOS 6)
See the docs: https://developer.apple.com/library/ios/documentation/Accounts/Reference/ACAccountStoreClassRef/Reference/Reference.html#//apple_ref/doc/uid/TP40011021-CH1-SW12
Try update for this:
ACAccountStore *account = [[ACAccountStore alloc] init];
ACAccountType *accountType = [account accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
// iOS 6
if ( [account respondsToSelector:#selector(requestAccessToAccountsWithType: options: completion:)] )
{
[account requestAccessToAccountsWithType:accountType options:nil
completion:^(BOOL granted, NSError *error)
{
dispatch_async(dispatch_get_main_queue(), ^{
if (granted)
{
//MY CODE
}
});
}];
}
// iOS 5
else if ( [account respondsToSelector:#selector(requestAccessToAccountsWithType: withCompletionHandler:)] )
{
[account requestAccessToAccountsWithType:accountType
withCompletionHandler:^(BOOL granted, NSError *error)
{
dispatch_async(dispatch_get_main_queue(), ^{
if (granted)
{
//MY CODE
}
});
}];
}
else
{
// iOS 4 or less
}
Thanks #CReaTuS, I want to clarify this up to some more bit, Note that in case of iOS6 we make SLRequest where in iOS5 we have to perform request using TWRequest. See below-
ACAccountStore *accountStore = [[ACAccountStore alloc] init];
ACAccountType *accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
if ( [accountStore respondsToSelector:#selector(requestAccessToAccountsWithType: options: completion:)] )
{
[accountStore requestAccessToAccountsWithType:accountType options:nil
completion:^(BOOL granted, NSError *error)
{
dispatch_async(dispatch_get_main_queue(), ^{
if (granted)
{
// Get the list of Twitter accounts.
NSArray *accountsArray = [accountStore accountsWithAccountType:accountType];
// For the sake of brevity, we'll assume there is only one Twitter account present.
// You would ideally ask the user which account they want to tweet from, if there is more than one Twitter account present.
if ([accountsArray count] > 0) {
// Grab the initial Twitter account to tweet from.
ACAccount *twitterAccount = [accountsArray objectAtIndex:0];
NSMutableDictionary *tempDict = [[NSMutableDictionary alloc] init];
[tempDict setValue:#"Twitter_Name" forKey:#"screen_name"];
[tempDict setValue:#"true" forKey:#"follow"];
//Code specific to iOS6 or later
SLRequest *followRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodPOST URL:[NSURL URLWithString:#"https://api.twitter.com/1.1/friendships/create.json"] parameters:tempDict];
// To unfollow hit URL-https://api.twitter.com/1.1/friendships/destroy.json
[followRequest setAccount:twitterAccount];
[followRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
NSString *output = [NSString stringWithFormat:#"HTTP response status: %i", [urlResponse statusCode]];
NSLog(#"%#", output);
if (error) {
dispatch_async(dispatch_get_main_queue(), ^{
//Update UI to show follow request failed
});
}
else {
dispatch_async(dispatch_get_main_queue(), ^{
//Update UI to show success
});
}
}];
}
}
});
}];
}
else if ( [accountStore respondsToSelector:#selector(requestAccessToAccountsWithType: withCompletionHandler:)] )
{
[accountStore requestAccessToAccountsWithType:accountType withCompletionHandler:^(BOOL granted, NSError *error)
{
dispatch_async(dispatch_get_main_queue(), ^{
if (granted)
{
// Get the list of Twitter accounts.
NSArray *accountsArray = [accountStore accountsWithAccountType:accountType];
// For the sake of brevity, we'll assume there is only one Twitter account present.
// You would ideally ask the user which account they want to tweet from, if there is more than one Twitter account present.
if ([accountsArray count] > 0) {
// Grab the initial Twitter account to tweet from.
ACAccount *twitterAccount = [accountsArray objectAtIndex:0];
NSMutableDictionary *tempDict = [[NSMutableDictionary alloc] init];
[tempDict setValue:#"Twitter_Name" forKey:#"screen_name"];
[tempDict setValue:#"true" forKey:#"follow"];
//Code specific to iOS5
TWRequest *followRequest = [[TWRequest alloc] initWithURL:[NSURL URLWithString:#"https://api.twitter.com/1/friendships/create.json"]
parameters:tempDict
requestMethod:TWRequestMethodPOST];
[followRequest setAccount:twitterAccount];
[followRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
NSString *output = [NSString stringWithFormat:#"HTTP response status: %i", [urlResponse statusCode]];
NSLog(#"%#", output);
if (error) {
dispatch_async(dispatch_get_main_queue(), ^{
//Update UI to show follow request failed
});
}
else {
dispatch_async(dispatch_get_main_queue(), ^{
//Update UI to show success
});
}
}];
}
}
});
}];
}
else
{
dispatch_async(dispatch_get_main_queue(), ^{
//Update UI to show follow request completely failed
});
}
Happy coding :)
Related
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook]) {
ACAccountStore *accountStore = [[ACAccountStore alloc] init];
ACAccountType *facebookAcc = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
NSDictionary *options = #{ (NSString *)ACFacebookAppIdKey: #"##########",
(NSString *)ACFacebookPermissionsKey: [NSArray arrayWithObject:#"email"],
(NSString *)ACFacebookAudienceKey: ACFacebookAudienceEveryone,
};
[accountStore requestAccessToAccountsWithType:facebookAcc options:options completion:^(BOOL granted, NSError *error){
if (granted) {
ACAccount *facebookAccount = [[accountStore accountsWithAccountType:facebookAcc] firstObject];
NSLog(#"facebook usre name: %#, Full name: %#", facebookAccount.username, facebookAccount);
}
else if (error)
NSLog(#"Error occured:%#", [error localizedDescription]);
}];
}
and I am getting
Error occurred:The Facebook server could not fulfill this access request: invalid app id
what should I write ACFacebookAppIdKey
go to https://developers.facebook.com/. Create new a new app for iOS or choose your app. At the Dashboard menu, you can see your App ID. This App ID you should put to the ACFacebookAppIdKey.
I have class that post a tweet to twitter using HTTP Post
here is a bit of code
PostTweet.h
#interface PostTweet : NSObject
- (void)postMyTweet;
#end
PostTweet.m
- (void)postMyTweet
{
accountStore = [[ACAccountStore alloc] init];
accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[accountStore requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error)
{
if (granted)
{
allAccounts = [accountStore accountsWithAccountType:accountType];
if ([allAccounts count] > 0)
{
userAccount = [allAccounts objectAtIndex:0];
userName = userAccount.username;
NSURL * reqURL = [NSURL URLWithString:ENDPOINT_MEDIA_UPLOAD];
NSDictionary * parameter = [NSDictionary dictionaryWithObject:tweetTitle forKey:#"status"];
SLRequest *twitterInfoRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter
requestMethod:SLRequestMethodPOST
URL:reqURL
parameters:parameter];
[twitterInfoRequest addMultipartData:tweetImage withName:PARAM_MEDIA type:CONTENT_TYPE_MULTIPART_FORM_DATA filename:nil];
[twitterInfoRequest setAccount:userAccount];
[twitterInfoRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
{
//show status after done
long result = [urlResponse statusCode];
//Let us say that every thing is ok and I got 200 response
if (result == 200)
{
NSLog(#"%ld",result);
}
}
];
}
}
else
{
NSLog(#"Not authorized");
}
}];
}
In my viewcontroller.m
- (void) actuallySendTweet
{
PostTweet * pt = [[PostTweet alloc] init];
[pt postTweet];
NSLog(#"Done");
}
The Question is: after calling The testMethod, How to wait for the http request response and I can do anything based on the response.
What happens now is that as soon as I call the testMethod the NSLog perform right away and does not wait for the http response.
First, if you wanted to coordinate two different threads dispatch_semaphore_t might be more appropriate than dispatch_group_t.
Second, and more importantly, you should not take an asynchronous method such as performRequestWithHandler, invoke it from the main queue in a synchronous manner. You never should be blocking the main queue.
Fortunately performRequestWithHandler gives us a handler block which we can use to perform actions after the tweet is done. In your comments, you say you simply want to update your HUD after the tweet, so you should do that performRequestWithHandler (dispatching that UI update back to the main queue, because, as the documentation says, "handler is not guaranteed to be called on any particular thread"):
- (void)postMyTweet
{
ACAccountStore *accountStore = [[ACAccountStore alloc] init];
ACAccountType *accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[accountStore requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error)
{
if (granted)
{
NSArray *allAccounts = [accountStore accountsWithAccountType:accountType];
if ([allAccounts count] > 0)
{
ACAccount *userAccount = [allAccounts objectAtIndex:0];
NSURL *reqURL = [NSURL URLWithString:ENDPOINT_MEDIA_UPLOAD];
NSDictionary *parameter = [NSDictionary dictionaryWithObject:tweetTitle forKey:#"status"];
SLRequest *twitterRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter
requestMethod:SLRequestMethodPOST
URL:reqURL
parameters:parameter];
[twitterRequest addMultipartData:tweetImage withName:PARAM_MEDIA type:CONTENT_TYPE_MULTIPART_FORM_DATA filename:nil];
[twitterRequest setAccount:userAccount];
[twitterRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
{
if (error)
NSLog(#"tweet fail; error = %#", error);
else
{
long result = [urlResponse statusCode];
if (result == 200)
NSLog(#"%ld",result);
else
NSLog(#"Unexpected response: %#", [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]]);
}
// Dispatch UI updates back to main queue
dispatch_async(dispatch_get_main_queue(), ^{
// do your MBProgressHUD stuff here
});
}];
}
}
else
{
NSLog(#"Not authorized");
}
}];
}
You also asked "How can I pass the HTTP response result to the viewcontroller?" You obviously do all of this in performRequestWithHandler, where you have the HTTP response (and the response data).
If you want postTweet to operate synchronously, then best practices would dictate that you don't submit it from the main queue (because, at the risk of sounding like a broken record, you never want to block the main queue). But you could have actuallySendTweet dispatch this tweet from a background queue, e.g.:
- (void) actuallySendTweet
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
PostTweet * pt = [[PostTweet alloc] init];
[pt postTweetSynchronously];
NSLog(#"Done");
dispatch_async(dispatch_get_main_queue(), ^{
// Now do any UI updates you want here.
// For example, do your MBProgressHUD update here.
});
});
}
- (void)postTweetSynchronously
{
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
ACAccountStore *accountStore = [[ACAccountStore alloc] init];
ACAccountType *accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[accountStore requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error)
{
if (granted)
{
NSArray *allAccounts = [accountStore accountsWithAccountType:accountType];
if ([allAccounts count] > 0)
{
ACAccount *userAccount = [allAccounts objectAtIndex:0];
NSURL *reqURL = [NSURL URLWithString:ENDPOINT_MEDIA_UPLOAD];
NSDictionary *parameter = [NSDictionary dictionaryWithObject:tweetTitle forKey:#"status"];
SLRequest *twitterRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter
requestMethod:SLRequestMethodPOST
URL:reqURL
parameters:parameter];
[twitterRequest addMultipartData:tweetImage withName:PARAM_MEDIA type:CONTENT_TYPE_MULTIPART_FORM_DATA filename:nil];
[twitterRequest setAccount:userAccount];
[twitterRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
{
// do whatever you want here, perhaps updating some class properties
// now that we're done, signal the semaphore
dispatch_semaphore_signal(semaphore);
}];
}
}
else
{
NSLog(#"Not authorized");
dispatch_semaphore_signal(semaphore); // make sure to signal here, too
}
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
As here you are using completion block. The thread does not wait for the execution of block.
So it you want that execution of block should complete and precess the data before finishing the execution of method, you can use,
dispatch_group_t
I am editing your method for that,
- (void)postMyTweet
{
accountStore = [[ACAccountStore alloc] init];
accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
[accountStore requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error)
{
if (granted)
{
allAccounts = [accountStore accountsWithAccountType:accountType];
if ([allAccounts count] > 0)
{
userAccount = [allAccounts objectAtIndex:0];
userName = userAccount.username;
NSURL * reqURL = [NSURL URLWithString:ENDPOINT_MEDIA_UPLOAD];
NSDictionary * parameter = [NSDictionary dictionaryWithObject:tweetTitle forKey:#"status"];
SLRequest *twitterInfoRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter
requestMethod:SLRequestMethodPOST
URL:reqURL
parameters:parameter];
[twitterInfoRequest addMultipartData:tweetImage withName:PARAM_MEDIA type:CONTENT_TYPE_MULTIPART_FORM_DATA filename:nil];
[twitterInfoRequest setAccount:userAccount];
[twitterInfoRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
{
//show status after done
long result = [urlResponse statusCode];
//Let us say that every thing is ok and I got 200 response
if (result == 200)
{
NSLog(#"%ld",result);
}
dispatch_group_leave(group);
}
];
}
}
else
{
NSLog(#"Not authorized");
dispatch_group_leave(group);
}
}];
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_release(group);
}
Now from this you can get idea.
I am trying to fetch user details but am currently unable to fetch images.This is the error I am getting:
{
error = {
code = 2500;
message = "An active access token must be used to query information about the current user.";
type = OAuthException;
};
}
This is my code:
if(!self.store)
{
ACAccountStore *store1 = [[ACAccountStore alloc] init];
self.store=store1;
[store1 release];
}
ACAccountType *fbAccountType =
[store accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
NSArray * permissions = #[#"read_stream", #"publish_stream",#"email", #"user_birthday",#"publish_actions",#"user_photos"];
NSDictionary * dict = #{ACFacebookAppIdKey : #"my_key", ACFacebookPermissionsKey : permissions, ACFacebookAudienceKey : ACFacebookAudienceOnlyMe};
// Request permission from the user to access the available Twitter accounts
[store requestAccessToAccountsWithType:fbAccountType options:dict completion:^(BOOL granted, NSError *error) {
__block NSString * statusText = nil;
if (granted) {
statusText = #"Logged in";
NSArray * accounts = [store accountsWithAccountType:fbAccountType];
store = [accounts lastObject];
account = [accounts objectAtIndex:0];
NSLog(#"account is: %#", account);
NSURL *requestURL = [NSURL URLWithString:#"https://graph.facebook.com/me?fields=picture"];
SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeFacebook
requestMethod:SLRequestMethodGET
URL:requestURL
parameters:nil];
request.account = account;
[request performRequestWithHandler:^(NSData *data,
NSHTTPURLResponse *response,
NSError *error) {
if(!error){
NSDictionary *list =[NSJSONSerialization JSONObjectWithData:data
options:kNilOptions error:&error];
NSLog(#"Dictionary contains: %#", list );
}
else{
//handle error gracefully
}
}];
}
If I use https://graph.facebook.com/me as url then it works fine. But I need the profile pic as well. What to do?
"fields" is a parameter, not a part of the URL itself. This works:
SLRequest *videoLimitsRequest = [SLRequest requestForServiceType:SLServiceTypeFacebook
requestMethod:SLRequestMethodGET
URL:[NSURL URLWithString:#"https://graph.facebook.com/me"]
parameters:#{#"fields": #"video_upload_limits"}];
FYI, token is added automatically when you attach account to the SLRequest.
you can run fql with accesstoken like this
https://graph.facebook.com/fql?q=SELECT name from user where uid = YourFAcebookID&access_token=ACCESSTOKEN
This will work for you.
This is a bit old but I forgot to answer then.
From FB api 3.2 onwards everything is managed within the api, for bot iOS 5 and 6 native login. Here is what I did:
FBRequestConnection *newConnection = [[FBRequestConnection alloc] init];
FBRequest *request = [FBRequest requestWithGraphPath:#"me/albums" parameters:nil HTTPMethod:#"GET"];
FBRequestHandler handler =
^(FBRequestConnection *connection, id result, NSError *error)
{
if(!error)
{
NSDictionary *list =(NSDictionary*)result;
int flag = 0;
for (int index = 0; index < [[list objectForKey:#"data"] count];index++)
{
if ([[[[list objectForKey:#"data"] objectAtIndex:index] objectForKey:#"name"] isEqualToString:#"Profile Pictures"])
{
[self fetchAlbumImages:[[[list objectForKey:#"data"] objectAtIndex:index] objectForKey:#"id"]];
flag = 1;
}
}
if (flag == 0)
{
[self fetchAlbumImages:#"No Album"];
}
}
else
{
}
};
[newConnection addRequest:request completionHandler:handler];
//[self.requestConnection cancel];
[newConnection start];
[newConnection release];
}
- (void) fetchAlbumImages:(NSString*)albumId
{
if ([albumId isEqualToString:#"No Album"])
{
NSMutableArray *albumArray = [[NSMutableArray alloc]init];
[self performSelectorOnMainThread:#selector(sendRegistrationRequest:) withObject:albumArray waitUntilDone:YES];
[albumArray release];
}
else
{
FBRequestConnection *newConnection = [[FBRequestConnection alloc] init];
FBRequest *request = [FBRequest requestWithGraphPath:[NSString stringWithFormat:#"%#/photos",albumId] parameters:nil HTTPMethod:#"GET"];
FBRequestHandler handler =
^(FBRequestConnection *connection, id result, NSError *error)
{
if(!error)
{
NSDictionary *list =(NSDictionary*)result;
NSMutableArray *albumArray = [[NSMutableArray alloc]init];
for (int index = 0; index < ([[list objectForKey:#"data"] count]<10?[[list objectForKey:#"data"] count]:10);index++)
{
[albumArray addObject:[[[list objectForKey:#"data"] objectAtIndex:index] objectForKey:#"source"]];
}
[self performSelectorOnMainThread:#selector(sendRegistrationRequest:) withObject:albumArray waitUntilDone:YES];
}
else
{
}
};
[newConnection addRequest:request completionHandler:handler];
//[self.requestConnection cancel];
self.requestConnection = newConnection;
[newConnection start];
[newConnection release];
}
}
I am trying to build simple prototype where I post some text to my facebook account. I have read the ios 6 facebook integration documentation and came up with following code. Everything seems to work fine until I hit the last block where I create SLRequest object in method postTextToFacebook and try to execute performRequestWithHandler with handler block. Control never does inside the handler block. I am assuming that performRequestWithHandler call is not successful in this case. Any one have done with successfully? Here is code for your reference.
#import <Social/Social.h>
#import "ViewController.h"
#implementation ViewController
#synthesize facebookAccount;
#synthesize accountStore;
#synthesize textToPost;
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
-(IBAction) postToFacebook:(id)sender
{
self.statusLabel.text = #"Logging in ...";
if(self.accountStore == nil)
{
self.accountStore = [[ACAccountStore alloc] init];
}
ACAccountType *facebookAccountType = [self.accountStore enter code hereaccountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
NSMutableDictionary *myOptions = [NSMutableDictionary dictionaryWithObjectsAndKeys:
#"172197712918906", ACFacebookAppIdKey,
[NSArray arrayWithObjects:#"email", #"user_about_me", #"user_likes", nil], ACFacebookPermissionsKey, ACFacebookAudienceFriends, ACFacebookAudienceKey, nil];
[self.accountStore requestAccessToAccountsWithType:facebookAccountType options:myOptions completion:^(BOOL granted, NSError *error){
__block NSString *statusText;
if(granted)
{
NSArray *accounts = [self.accountStore accountsWithAccountType:facebookAccountType];
self.facebookAccount = [accounts lastObject];
[myOptions setObject:[NSArray arrayWithObjects:#"publish_stream", nil] forKey:ACFacebookPermissionsKey];
[self.accountStore requestAccessToAccountsWithType:facebookAccountType options:myOptions completion:^(BOOL granted, NSError *error) {
__block NSString *statusText1;
if(granted && error == nil)
{
NSArray *accounts = [self.accountStore accountsWithAccountType:facebookAccountType];
self.facebookAccount = [accounts lastObject];
[self postTextToFacebook];
statusText1 = #"Text Posted.";
}
else{
statusText1 = #"Publish Failed.";
}
dispatch_async(dispatch_get_main_queue(), ^{
self.statusLabel.text = statusText1;
});
}];
}
else{
statusText = #"Login Failed.";
NSLog(#"Error = %#",error);
}
}];
}
-(void) postTextToFacebook
{
NSDictionary *parameters = #{#"message":self.textToPost.text};
NSURL *feedURL = [NSURL URLWithString:#"https://graphs.facebook.com/me/feed"];
SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeFacebook requestMethod:SLRequestMethodPOST URL:feedURL parameters:parameters];
request.account = self.facebookAccount;
[request performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
NSLog(#"Facebook request received, status code %d", urlResponse.statusCode);
NSString *response = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"Response data: %#", response);
//handle errors
if(error == nil)
{
dispatch_async(dispatch_get_main_queue(), ^{
self.statusLabel.text = #"text posted to facebook";
});
}
}];
}
#end
Your url should be
https://graph.facebook.com/me/feed
instead of
https://graphs.facebook.com/me/feed
I was having a same issue and got an NSURLErrorDomain -1003 error on it.
In iOS 6, the user can login to Facebook via Settings>Facebook. There is a section on that view where the apps for which the user may choose to allow/disallow use of the Facebook account are listed.
I have integrated the FacebookSDK.framework into my app, and a line appears for the app in this list. Only, the name of my app is not listed, and neither is its app icon.
I have done several searches and can't seem to find a way to get the name/icon added to the list. Can anyone point me in the right direction?
You'll need to use the account store methods to request access:
-(void)authenticateFacebook {
if([UIActivityViewController class] ) {
NSArray *faceBookPermissions = #[#"publish_stream"];
////ACFacebookAppVersionKey: #"1.0",
NSDictionary *faceBookOptions = #{
ACFacebookAppIdKey: #"xxxxxxxx",
ACFacebookPermissionsKey:faceBookPermissions,
ACFacebookAudienceKey:ACFacebookAudienceFriends
};
AppDelegate *del = (AppDelegate *)[[UIApplication sharedApplication] delegate];
if(del.accountStore == nil) {
del.accountStore = [[ACAccountStore alloc] init];
}
if(del.facebookAccount == nil) {
ACAccountType *facebookAccountType = [del.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
[del.accountStore requestAccessToAccountsWithType:facebookAccountType
options:faceBookOptions
completion:^(BOOL granted, NSError *error)
{
if (granted) {
NSArray *accounts = [del.accountStore accountsWithAccountType:facebookAccountType];
del.facebookAccount = [accounts lastObject];
NSLog(#"got an account");
[self performSelectorOnMainThread:#selector(gotAnAccount) withObject:self waitUntilDone:NO];
} else {
NSLog(#"No account");
//fail gracefully
[self performSelectorOnMainThread:#selector(noAccount) withObject:self waitUntilDone:NO];
}
}];
}
}
Once that is done you can post to facebook with your app id as follows:
-(void)postToFacebook:(NSDictionary *)parameters {
AppDelegate *del = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSURL *feedURL = [NSURL URLWithString:#"https://graph.facebook.com/me/feed"];
SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeFacebook
requestMethod:SLRequestMethodPOST
URL:feedURL
parameters:parameters];
request.account = del.facebookAccount;
[request performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
NSString *alertText;
if (error) {
alertText = [NSString stringWithFormat:
#"error: domain = %#, code = %d",
error.domain, error.code];
[self performSelectorOnMainThread:#selector(errorWithRequest:) withObject:alertText waitUntilDone:NO];
} else {
alertText = #"Posted action, id: %#";
[self performSelectorOnMainThread:#selector(cancelButtonAction:) withObject:nil waitUntilDone:NO];
}
NSLog(#"%#",alertText);
}];
}
You'll need your app delegate to have the accountStore and account variables and then create the #selector methods used. Note that the completion handlers should run on the main thread if they do anything with the UI or you'll be sat waiting a while for the completion handler UI code to run.