Open Twitter Setting from ACAccountStore (iOS 5.1 TWITTER) - iphone

in iOS 5.0 i was opening Twitter setting from my app by
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"prefs:root=TWITTER"]];
but , this features is removed in iOS 5.1 , hence i can not able to open twitter setting .
Now i am using
+ (void)makeRequestsWithURL: (NSURL *)url {
// Create an account store object.
ACAccountStore *accountStore = [[ACAccountStore alloc] init];
// Create an account type that ensures Twitter accounts are retrieved.
ACAccountType *accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[self canTweetStatus];
// Request access from the user to use their Twitter accounts.
[accountStore requestAccessToAccountsWithType:accountType withCompletionHandler:^(BOOL granted, NSError *error) {
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];
// Create a request, which in this example, posts a tweet to the user's timeline.
// This example uses version 1 of the Twitter API.
// This may need to be changed to whichever version is currently appropriate.
TWRequest *postRequest = [[TWRequest alloc] initWithURL:url parameters:nil requestMethod:TWRequestMethodPOST];
// Set the account used to post the tweet.
[postRequest setAccount:twitterAccount];
// Perform the request created above and create a handler block to handle the response.
[postRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
NSString *output = [NSString stringWithFormat:#"HTTP response status: %i", [urlResponse statusCode]];
iOS5Twitter *twitter5 = [[iOS5Twitter alloc] init];
[twitter5 performSelectorOnMainThread:#selector(displayText:) withObject:output waitUntilDone:NO];
[twitter5 release]; }];
}
}
}];
}
for making request, i am able to check wether i am loged in or not by the
if ([TWTweetComposeViewController canSendTweet])
but now i want : if i am not loged in it would be show an alert like shown in image and want to move to the twitter setting . is it possible ? or i have to manually go ti twitter setting ?

It is little tricky , i get by the removing the subviews in *TWTWeetComposeViewController*, so it shows only alert when user is not loged in and by the clicking on setting button , we can open Setting page in my app.
+ (void)setAlertForSettingPage :(id)delegate
{
// Set up the built-in twitter composition view controller.
TWTweetComposeViewController *tweetViewController = [[TWTweetComposeViewController alloc] init];
// Create the completion handler block.
[tweetViewController setCompletionHandler:^(TWTweetComposeViewControllerResult result) {
[delegate dismissModalViewControllerAnimated:YES];
}];
// Present the tweet composition view controller modally.
[delegate presentModalViewController:tweetViewController animated:YES];
//tweetViewController.view.hidden = YES;
for (UIView *view in tweetViewController.view.subviews){
[view removeFromSuperview];
}
}
here , deleate is your viewcontroller , if you are using this method inside your viewcontroller just use self instead of delegate.

iOS 6 uses SLComposeViewController instead of TWTweetComposeViewController, so now you have to do this if you want it to work on iOS 6 and iOS 5:
UIViewController *tweetComposer;
if([SLComposeViewController class] != nil)
{
tweetComposer = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeTwitter];
[(SLComposeViewController *)tweetComposer setCompletionHandler:^(SLComposeViewControllerResult result)
{
// do whatever you want
}];
}
else
{
tweetComposer = [[TWTweetComposeViewController alloc] init];
[(TWTweetComposeViewController *)tweetComposer setCompletionHandler:^(TWTweetComposeViewControllerResult result)
{
// do whatever you want
}];
}
for (UIView *view in [[tweetComposer view] subviews])
[view removeFromSuperview];
[self presentViewController:tweetComposer animated:NO completion:nil];

Building upon Senior's and PJR's answers above, this is what worked for me.
Same as Senior's, except with a dimissViewController in the completion handler. For me this got around the problem that the empty view controller would stick around after I returned to the app from the settings. It would overlay my view controller and make it useless.
Brilliant solution, thanks Senior and PJR.
UIViewController *tweetComposer;
if([SLComposeViewController class] != nil)
{
tweetComposer = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeTwitter];
[(SLComposeViewController *)tweetComposer setCompletionHandler:^(SLComposeViewControllerResult result)
{
[self dismissViewControllerAnimated:NO completion:nil];
}];
}
else
{
tweetComposer = [[TWTweetComposeViewController alloc] init];
[(TWTweetComposeViewController *)tweetComposer setCompletionHandler:^(TWTweetComposeViewControllerResult result)
{
[self dismissViewControllerAnimated:NO completion:nil];
}];
}
for (UIView *view in [[tweetComposer view] subviews])
[view removeFromSuperview];
[self presentViewController:tweetComposer animated:NO completion:nil];

To remove the post view,
instead using this code:
for (UIView *view in [[tweetComposer view] subviews])
[view removeFromSuperview];
use this:
tweetComposer.view.alpha = 0;
works both for twitter and facebook.

Related

Update UI after requestAccessToAccountsWithType

I'm developing an app to help me understand OBJECTIVE-X/OSX.
The app simply connects to Facebook and sends a notification using NSUserNotification.
It is working fine, but now I want to add some UI to the mix.
To make the example simpler, I want to update a label (NSTextField) to show the status of the Facebook connection.
Connecting…
Connected
Failed
I have the following code in one File FacebookRequest.m
- (void) connectFacebook{
if(self.account == nil){
self.account = [[ACAccountStore alloc]init];
}
ACAccountType *facebookAccount = [self.account
accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
NSDictionary *options = #{
ACFacebookAppIdKey: #"MY_CODE",
ACFacebookPermissionsKey: #[#"email",
#"user_about_me",
#"user_likes",
#"manage_notifications",
#"user_activities"],
ACFacebookAudienceKey: ACFacebookAudienceFriends
};
[self.account requestAccessToAccountsWithType:facebookAccount
options:options
completion:^(BOOL success, NSError *error){
if(success){
NSArray *accounts = [self.account accountsWithAccountType:facebookAccount];
self.account = [accounts lastObject];
}
else{
NSLog(#"Erro %#", [error description]);
}
}];
}
and the following one in my AppDelegate.m
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[self.statusFacebook setStringValue:#"Connecting…"];
FacebookRequest *request = [[FacebookRequest alloc]init];
[request connectFacebook];
}
What is the best way to update the UI after the request is complete and I have an account?
I'm having troubles since the request is asynchronous and I can't return any value inside the requestAccessToAccountsWithType block. Another point is that if I put some "ifs" to check if my account is nil after it, it will be executed before the block has finished executing, so the account would still be nil.
Thanks!
PS.: Sorry for the English if it is not clear enough.
You may use NSNotificationCenter for this purpose:
[self.account requestAccessToAccountsWithType:facebookAccount
options:options
completion:^(BOOL success, NSError *error){
if(success){
NSArray *accounts = [self.account accountsWithAccountType:facebookAccount];
self.account = [accounts lastObject];
// You post a notification that the UI should update here
[[NSNotificationCenter defaultCenter] postNotificationName:#"UpdateUI" object:nil];
}
else{
NSLog(#"Erro %#", [error description]);
}
}];
Then, you add your viewController that should update its UI as an observer of this notification:
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(updateUI) name:#"UpdateUI" object:nil];
}
- (void)updateUI {
// Here you actually update your UI
}
p.s. if you are not using arc you also remove the observer in dealloc:
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];

Integrate facebook login and fetch user details along with tabbarcontroller in ios6

I have implemented facebook login in my app.
1----> I was able to do facebook login but after that logged in user is able to continue with my app i.e a tabbarController with three tab items appears and simultaneously I need to fetch facebook user details (email,firstname,lastname etc)
But I was unable to retrieve details. I do not understand where am I going wrong.
In my ViewController.m:
- (IBAction)performLogin:(id)sender
{
AppAppDelegate *appDelegate = (AppAppDelegate *) [[UIApplication sharedApplication] delegate];
[appDelegate openSessionWithAllowLoginUI:YES];
UITabBarController *tabBarController=[[UITabBarController alloc]init];
SearchViewController *searchViewController=[[SearchViewController alloc]initWithNibName:#"SearchViewController" bundle:nil];
UProfile *uprofile=[[UProfile alloc]initWithNibName:#"UProfile" bundle:nil];
userprofile.title=#"My Profile";
LogOut *logout=[[LogOut alloc]initWithNibName:#"LogOut" bundle:nil];
logout.title=#"Sign out";
tabBarController.viewControllers=[NSArray arrayWithObjects:searchViewController,uprofile,logout, nil];
[self presentModalViewController:tabBarController animated:YES];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(sessionStateChanged:)
name:FBSessionStateChangedNotification
object:nil];
}
- (void)sessionStateChanged:(NSNotification*)notification {
if (FBSession.activeSession.isOpen) {
[FBRequestConnection
startForMeWithCompletionHandler:^(FBRequestConnection *connection,
id<FBGraphUser> user,
NSError *error) {
if (!error) {
NSString *fbUserEmail= #"";
NSLog(#"%#",user);
fbUserEmail=[user objectForKey:#"email"];
AppAppDelegate *appDelegate = (AppAppDelegate *) [[UIApplication sharedApplication] delegate];
appDelegate.fbEmail=fbUserEmail;
}
}
];
}
}
But here without showing facebook login page I am getting tabbarController and I am unable to retrieve user details.
How can I show facebook login page first and then tabbarController with user details?
After successful login into facebook how can I continue with my app with a tabbarcontroller with first tabitem(corresponding view )selected?
Please help me out in sorting this issue...Please
You will need to set the readPermissions for getting the email for this method, by passing it an NSArray with object "email". The remaining information such as name etc is returned by default.
+ (BOOL)openActiveSessionWithReadPermissions:(NSArray*)readPermissions
allowLoginUI:(BOOL)allowLoginUI
completionHandler:(FBSessionStateHandler)handler;
of the facebook sdk. If im not mistaken, unless specified permission is "email" then the email object of the user dictionary is nil. Modify your state changed handler perhaps to request the user details such as email. Inside the sessionStateChanged: handler if session is open u may call a method that simply does this
if (FBSession.activeSession.isOpen) {
[[FBRequest requestForMe] startWithCompletionHandler:
^(FBRequestConnection *connection,
NSDictionary<FBGraphUser> *user,
NSError *error) {
if (!error) {
NSLog(#"%#", user);
NSLog(#"%#", [user objectForKey:#"email"]);
}
}];
}

Add Facebook SDK to my xCode project with Storyboard

I am following Getting Started with the Facebook SDK for iOS v3.1 to add Facebook SDK to my xCode project with Storyboard.
I did all the steps that described there.
We have a HelloFacebookSample in the Sample folder of Facebook SDK. it includes this code:
- (void)viewDidLoad {
[super viewDidLoad];
// Create Login View so that the app will be granted "status_update" permission.
FBLoginView *loginview = [[FBLoginView alloc] init];
loginview.frame = CGRectOffset(loginview.frame, 5, 5);
loginview.delegate = self;
[self.view addSubview:loginview];
[loginview sizeToFit];
}
// Post Status Update button handler; will attempt to invoke the native
// share dialog and, if that's unavailable, will post directly
- (IBAction)postStatusUpdateClick:(UIButton *)sender {
// Post a status update to the user's feed via the Graph API, and display an alert view
// with the results or an error.
NSString *name = self.loggedInUser.first_name;
NSString *message = [NSString stringWithFormat:#"Updating status for %# at %#",
name != nil ? name : #"me" , [NSDate date]];
// if it is available to us, we will post using the native dialog
BOOL displayedNativeDialog = [FBNativeDialogs presentShareDialogModallyFrom:self
initialText:nil
image:nil
url:nil
handler:nil];
if (!displayedNativeDialog) {
[self performPublishAction:^{
// otherwise fall back on a request for permissions and a direct post
[FBRequestConnection startForPostStatusUpdate:message
completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
[self showAlert:message result:result error:error];
self.buttonPostStatus.enabled = YES;
}];
self.buttonPostStatus.enabled = NO;
}];
}
}
Then sample works fine, but when I want to have it on my own project, I have this problem:
It is successfully added the FBLoginView to my self.view. but when I Login and then want to post something I just go to this page:
Finally I found the problem. I needed to add these codes to my AppDelegate:
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
// attempt to extract a token from the url
return [FBSession.activeSession handleOpenURL:url];
}
- (void)applicationWillTerminate:(UIApplication *)application {
// FBSample logic
// if the app is going away, we close the session object
[FBSession.activeSession close];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// FBSample logic
// We need to properly handle activation of the application with regards to SSO
// (e.g., returning from iOS 6.0 authorization dialog or from fast app switching).
[FBSession.activeSession handleDidBecomeActive];
}
They were not described in the link. It could be better to let the new users know about these details.

Trying to switch views using a button only in a specific case

Using a Parse Framework, I am trying to have a user login to an app and if the login works when the user presses the login button, I want the view to change. In this specific case if(!error) I want the view to switch. Assuming the second view is called PostingViewController, how could I make this work?
-(IBAction)signUpButton:(id)sender
{
NSString *userInput = usernameInputField.text;
NSString *userPassword = passwordInputField.text;
PFUser *user = [PFUser user];
user.username = userInput;
user.password = userPassword;
[user signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if(!error){
}
else{
NSLog(#"there was a problem");
}
}];
}
simply create an object of PostingViewController object and push it to the current navigationController
some thing similar to this might be of help...
PostingViewController *vc = [[PostingViewController alloc] initWithNibName:#"your_nib_name" andBundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:vc withAnimation:YES];
[vc release];

Game Center inviting friends programmatically

I'm facing difficulty inviting a friend to the match.
GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease];
request.minPlayers = 2;
request.maxPlayers = 2;
request.playersToInvite = [NSArray arrayWithObjects: #"G:1102359306",nil ];
// GKMatchmakerViewController *mv = [[GKMatchmakerViewController alloc] initWithMatchRequest:request];
// [self presentModalViewController:mv animated:YES];
[[GKMatchmaker sharedMatchmaker] findMatchForRequest:request withCompletionHandler:^(GKMatch *match, NSError *error) {
if (error) {
NSLog([error description]);
}
else if (match != nil) {NSLog(#"good match");
//self.chatMatch = match;
//self.chatMatch.delegate = self;
//[self chatReady];
}
else {
NSLog(#"other error");
}
}];
The problem is I never receive the invitation notification on second device logged to the account - G:1102359306.
When I use GKMatchmakerViewController (uncomment above 2 lines) and comment GKMatchmaker block I have automatically checked the good friend - G:1102359306 and when I invites him the notification with accept/decline is shown, that's how I know it's correct.
Do you see anything wrong with the code above? I want to use my own UI to handle the multiplayer mode. The strange problem is I also don't see in console any logs good match/other error, and the [error description] is only printed when I call the above code twice - it says that the previous req was canceled.
You cannot programmatically invite a specific set of players to a match. The findMatchForRequest:withCompletionHandler: documentation says this:
The match request’s playersToInvite property is ignored; to invite a specific set of players to the match, you must display a matchmaker view controller.
There is no public API that does what you want.