When I run [_accountStore requestAccessToAccountsWithType: ...] I am getting no response. My completion handler isn't being called. However I do have access to twitter.
// Step 0: Check that the user has local Twitter accounts
if ([SLComposeViewController
isAvailableForServiceType:SLServiceTypeTwitter]) {
NSLog(#"OH YES!!!");
// Step 1: Obtain access to the user's Twitter accounts
ACAccountType *twitterAccountType = [_accountStore accountTypeWithAccountTypeIdentifier: ACAccountTypeIdentifierTwitter];
NSLog(#"OH YES!!!");
[_accountStore requestAccessToAccountsWithType:twitterAccountType options:nil
completion:^(BOOL granted, NSError *error)
{
NSLog(#"Im in!");
if (granted == YES)
{
NSArray *arrayOfAccounts = [_accountStore
accountsWithAccountType:twitterAccountType];
if ([arrayOfAccounts count] > 0)
{
ACAccount *twitterAccount = [arrayOfAccounts lastObject];
NSLog(#"%#", twitterAccount.userFullName);
NSLog(#"%#", twitterAccount.username);
NSLog(#"%#", twitterAccount.credential);
NSLog(#"%#", twitterAccount.identifier);
}
}else{
NSLog(#"Failed muahahaha");
}
}];
}
Why is this happening?
Make shure _accountStore is initialized for example with
_accountStore = [[ACAccountStore alloc] init];
Related
I'm trying to get email from my logged in user using Facebook SDK. Here are 2 of my login methods
-(void)loginButtonClicked {
FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
[login logInWithReadPermissions: #[#"public_profile", #"email", #"user_friends"]
fromViewController:self
handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
if (error) {
NSLog(#"Process error");
} else if (result.isCancelled) {
NSLog(#"Cancelled");
} else {
[self getFBUSerData];
NSLog(#"Logged in");
}
}];
}
- (void) getFBUSerData {
if (FBSDKAccessToken.currentAccessToken != nil) {
[[[FBSDKGraphRequest alloc] initWithGraphPath:#"me" parameters:nil]
startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
if (!error) {
NSLog(#"fetched user:%# and Email : %#", result,result[#"email"]);
}
}];
}
}
The result in the log:
(lldb) po result
{
id = 42357***4506554;
name = "Fname Lname";
}
But no email or friends list. Any help how to get those?
You have to assign the parameters you need to get in getFBUserData().
Something like this:
- (void) getFBUSerData {
if (FBSDKAccessToken.currentAccessToken != nil) {
NSDictionary *dict = [[NSDictionary alloc] initWithObjects:#[#"id, name, first_name, last_name, picture.type(large), email"] forKeys:#[#"fields"]];
[[[FBSDKGraphRequest alloc] initWithGraphPath:#"me" parameters:dict]
startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
if (!error) {
NSLog(#"fetched user:%# and Email : %#", result,result[#"email"]);
}
}]; }
}
When running this code...
-(IBAction)loginWithTwitter:(id)sender {
NSLog(#"Logging in with twitter");
ACAccountStore *accountStore = [[ACAccountStore alloc]init];
ACAccountType *accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[accountStore requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error) {
if (error) {
[self showError:error];
return;
}
if (granted) {
NSArray *accountsArray = [accountStore accountsWithAccountType:accountType];
if ([accountsArray count] > 1) {
NSLog(#"Multiple twitter accounts");
}
ACAccount *twitterAccount = [accountsArray objectAtIndex:0];
NSLog(#"%#", twitterAccount);
[self pushMainController];
}
}];
}
There is a 5-10 second delay before the pushMainControlleris actually called, even though the account information is logged almost immediately (after pre-authorization). If I move the pushMainController call after the block however, it happens immediately, the only problem being that a user isn't necessarily logged in at that point. I understand that it can take a second for a block to have a response due to variables such as network connectivity, but can someone help me understand this?
The completion block is not being done on the main queue. You need to ensure your UI code gets done on the main thread:
[accountStore requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error) {
if (error) {
[self showError:error];
return;
}
if (granted) {
NSArray *accountsArray = [accountStore accountsWithAccountType:accountType];
if ([accountsArray count] > 1) {
NSLog(#"Multiple twitter accounts");
}
ACAccount *twitterAccount = [accountsArray objectAtIndex:0];
NSLog(#"%#", twitterAccount);
dispatch_async(dispatch_get_main_queue(), ^{
[self pushMainController];
});
}
}];
You may have to wrap the showError call as well.
I am using the code bellow to get the list of all of users friends and check how many of them have installed the app so i can show their scores, and unlock some content for the user.
I can't find solid info about the field installed which seams to be perfect for this case.(If it specifies the user has installed the app which made the request :) )
[FBRequestConnection startWithGraphPath:#"me/friends"
parameters: #{ #"fields" : #"id,installed"}
HTTPMethod:nil
completionHandler:^(FBRequestConnection *connection,
id result,
NSError *error) {
if (!error) {
// Get the result
NSArray *resultData = result[#"data"];
// Check we have data
if ([resultData count] > 0) {
// Loop through the friends returned
for (NSDictionary *friendObject in resultData) {
// Check if devices info available
if (friendObject[#"installed"]) {
//Do some work if user has installed my game
}
}
}
}
}];
-(void)FBFriendList
{
if (!FBSession.activeSession.isOpen)
{
// if the session is closed, then we open it here, and establish a handler for state changes
[FBSession openActiveSessionWithReadPermissions:nil allowLoginUI:YES completionHandler:^(FBSession *session,FBSessionState state, NSError *error)
{
if (error)
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error" message:error.localizedDescription delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
}
else if(session.isOpen)
{
[self FB_Common_Friend];
}
}];
return;
}
}
-(void)FB_Common_Friend
{
FBRequest *request = [FBRequest requestWithGraphPath:#"me/friends" parameters:#{#"fields":#"name,installed,first_name,picture"} HTTPMethod:#"GET"];
[request startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error)
{
NSLog(#"%#",result);
int count = 0;
NSMutableArray *frnd_arr = [result objectForKey:#"data"];
for (int i = 0; i < [frnd_arr count]; i++)
{
if([[[frnd_arr objectAtIndex:i] objectForKey:#"installed"] boolValue])
{
count++;
}
}
app.fb_frnd_count = count;
}];
}
I have app where I am doing the Twitter integration.
I am able to successfully tweets.
Now when I want to de-activate, I am using below.
SLRequest *postRequest1 = [SLRequest requestForServiceType:SLServiceTypeTwitter
requestMethod:SLRequestMethodPOST URL:
[NSURL URLWithString:#"https://api.twitter.com/1/account/end_session.json"]
parameters: [NSDictionary dictionaryWithObject:#"" forKey:#"status"]];
Problem is API with 1 is deprecated and I don't find this method in 1.1.
Is there any alternate for this?
Also what I notice is when I try to activate again, the permission is not asked. It directly send tweet. It ask tweet permission for the first time only. Not after de-activate -- Re-activate process. Is this is how Twitter behaves?
Edit 1
Code I use for all tweet is as below...
if ([self userHasAccessToTwitter]) {
ACAccountStore *account = [[ACAccountStore alloc] init];
ACAccountType *accountType = [account accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
// Request access from the user to access their Twitter account
[account requestAccessToAccountsWithType:accountType options:NULL completion:^(BOOL granted, NSError *error)
{
if (granted == YES)
{
///////////////////////////////////////////////
// SEND TEXT ONLY ///
///////////////////////////////////////////////
[[NSUserDefaults standardUserDefaults] setValue:#"yes" forKey:#"twitterLogin"];
[[NSUserDefaults standardUserDefaults] synchronize];
// Populate array with all available Twitter accounts
NSString *message1 = [NSString stringWithFormat:#"Hi! I am using twitter integration."];
NSArray *arrayOfAccounts = [account accountsWithAccountType:accountType];
if ([arrayOfAccounts count] > 0)
{
//use the first account available
ACAccount *acct = [arrayOfAccounts objectAtIndex:0];
SLRequest *postRequest1 = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodPOST URL:[NSURL URLWithString:#"http://api.twitter.com/1.1/statuses/update.json"] parameters: [NSDictionary dictionaryWithObject:message1 forKey:#"status"]];
[postRequest1 setAccount:acct];//set account
[postRequest1 performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
if(error) {
NSLog(#"error == %#", error);
} else {
NSLog(#"good to go -1- %i", [urlResponse statusCode]);
}
}];
}
}
}];
}
end_session in API v1 never worked as it should anyway. Starting from 1.1 this method was removed and there's no alternative method. The user should decide if he wants to revoke your application access to his twitter account. The only thing you could do is to delete the auth_token.
I am using AVFoundation to capture video. All seems to be well in my app until I get to here:
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput
didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL
fromConnections:(NSArray *)connections
error:(NSError *)error
{
NSLog(#"didFinishRecordingToOutputFileAtURL - enter");
BOOL RecordedSuccessfully = YES;
if ([error code] != noErr)
{
// A problem occurred: Find out if the recording was successful.
id value = [[error userInfo] objectForKey:AVErrorRecordingSuccessfullyFinishedKey];
if (value)
{
RecordedSuccessfully = [value boolValue];
}
}
if (RecordedSuccessfully)
{
//----- RECORDED SUCESSFULLY -----
NSLog(#"didFinishRecordingToOutputFileAtURL - success");
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:outputFileURL])
{
[library writeVideoAtPathToSavedPhotosAlbum:outputFileURL
completionBlock:^(NSURL *assetURL, NSError *error)
{
if (error)
{
}
}];
}
[library release];
}
}
When running it on a device I receive the "didFinishRecordingToOutputFileAtURL - success" message, and then it crashes and I get this error:
Video /private/var/mobile/Applications/EDC62CED-3710-45B2-A658-A2FE9238F517/tmp/output.mov cannot be saved to the saved photos album: Error Domain=NSOSStatusErrorDomain Code=-12950 "Movie could not be played." UserInfo=0xe6749b0 {NSLocalizedDescription=Movie could not be played.}
I haven't been able to find a whole lot of information about this anywhere and am not really sure what's going on.
Here's the code with the temporary output URL:
NSString *outputPath = [[NSString alloc] initWithFormat:#"%#%#", NSTemporaryDirectory(), #"output.mov"];
NSURL *outputURL = [[NSURL alloc] initFileURLWithPath:outputPath];
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:outputPath])
{
NSError *error;
if ([fileManager removeItemAtPath:outputPath error:&error] == NO)
{
//Error - handle if requried
}
}
[outputPath release];
//Start recording
[movieFileOutput startRecordingToOutputFileURL:outputURL recordingDelegate:self];
[outputURL release];
I've already tried releasing the outputURL elsewhere after it saves, and that didn't help, so I don't think that's it.
I figured this out. I was an idiot and kept overlooking the fact that I didn't actually connect the video input to the capture session. Whoops.