Facebook iOS - handleOpenURL & Tabbar Application - iphone

I'm having difficulties getting the Facebook Log In to kick back to the right view in my app and call the appropriate facebook functions.
In the example Facebook has simply [controller facebook] that is the view they start with. I am using a tabbar application though so I don't have the necessary reference. I made a pointer to the desired view and used it... it opened correctly but would not call any of the methods associated with facebook, specifically:
(void)fbDidLogin;
(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [[*NotReferencedViewController* facebook] handleOpenURL:url];
}
Has anyone else run into this?

Not sure what example you're talking about, but you should create and store your Facebook object in a central place such as your Model or UIApplicationDelegate. Then it would be accessible through singletons so you always have access to it, for example:
[[UIApplication sharedApplication] delegate].facebook
So you can then access the facebook object from whatever view controllers need it.
When you do something like
NSArray* permissions = [[NSArray arrayWithObjects:#"email", #"read_stream", #"publish_stream", nil] retain];
[facebook authorize:permissions delegate:self];
specifying delegate:self means you will implement methods in that class that Facebook can call to inform you of certain events. One of those methods is fbDidLogin, and in there you can do whatever you need to:
-(void)authorizeFacebook {
NSArray* permissions = [NSArray arrayWithObjects:#"email", #"read_stream", #"publish_stream", nil];
[facebook authorize:permissions delegate:self];
}
// if the authorization succeeds it will come back to your app and call the method below
-(void)fbDidLogin {
// switch view, call the facebook graph, or do whatever else you like
}
You could do this in the app delegate itself, or in a view controller.
You can see the facebook delegate methods by inspecting the .h files of the facebook SDK: Facebook.h, FacebookRequest.h, etc.
Edit
And your handleOpenURL: method should look exactly as it does in fb's example (assuming you are not handling other url schemes):
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [facebook handleOpenURL:url];
}
http://developers.facebook.com/docs/guides/mobile/#ios

Related

Parse.com Facebook Login stays on "Loading" iOS

I'm using Parse, with the LogInViewController. I added Facebook on the logIn View.
When someone wants to connect with Facebook, it opens the browser, the user accepts the application and then he returns to the app. But when he returns on the app, he stays on "loading" and nothing happens.
However if the user restart the app, it works.
Only when it's the first connexion for the user I have this problem.
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if (![PFUser currentUser]) {
// Customize the Log In View Controller
PFLogInViewController *logInViewController = [[PFLogInViewController alloc] init];
[logInViewController setDelegate:self];
[logInViewController setFacebookPermissions:[NSArray arrayWithObjects:#"friends_about_me", nil]];
[logInViewController setFields: PFLogInFieldsFacebook | PFLogInFieldsDismissButton];
// Present Log In View Controller
[self presentViewController:logInViewController animated:YES completion:NULL];
}
}
I think the problem isn't in my code because I use the default code of Parse but I'm not sure.
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [FBAppCall handleOpenURL:url
sourceApplication:sourceApplication
withSession:[PFFacebookUtils session]];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
/*
Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
*/
[FBAppCall handleDidBecomeActiveWithSession:[PFFacebookUtils session]];
}
- (void)applicationWillTerminate:(UIApplication *)application {
/*
Called when the application is about to terminate.
Save data if appropriate.
See also applicationDidEnterBackground:.
*/
[[PFFacebookUtils session] close];
}

How do I respond to successful login with Dropbox API on iOS?

It checks whether the user is logged into dropbox when my app is launched. If they are, it continues with code relating to dropbox. If not, it shows them a login screen using [[DBSession sharedSession] link];.
From the login screen comes this delegate, if authorization fails:
-(void)sessionDidReceiveAuthorizationFailure:(DBSession *)session userId:(NSString *)userId {
[[DBSession sharedSession] link];
}
But there doesn't seem to be something for when authorization succeeds. How do I deal with this scenario? I need to start running the necessary code once they're linked with dropbox.
You handle successful login from the Dropbox API in the
-(BOOL) application:(UIApplication *)application handleOpenURL:(NSURL *)url function
-(BOOL) application:(UIApplication *)application handleOpenURL:(NSURL *)url {
if ([[DBSession sharedSession] handleOpenURL:url]) {
//Successfully Logged in to Dropbox
return YES;
}
return NO;
}
As part of applicationDidFinishLaunching you could initiate the dropbox api you could do the following.
dispatch_async(dispatch_get_main_queue(), ^{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
DBSession* dbSession = [[[DBSession alloc] initWithAppKey:#"appKey" appSecret:#"appSecret" root:kDBRootAppFolder] autorelease];
dbSession.delegate = self;
[DBSession setSharedSession:dbSession];
[[NSNotificationCenter defaultCenter] postNotificationName:kSharedSessionAvailability object:[NSNumber numberWithBool:dbSession != nil ? YES : NO]];
});
But normally you simply get your session and use it later via the restClient.

fbDidLogin not called - iOS

I'm trying to implement facebook to my iOS app for a school project however I ran into a bit of a snag, namely the fbDidLogin method is not called.
I have created a sample object called FBFetcher as so:
#interface FBFetcher : NSObject <FBDialogDelegate,FBSessionDelegate,FBRequestDelegate> {
Facebook *facebook;
FBFetcher *facebookFetcher;
}
-(void)login;
#property (retain) Facebook *facebook;
#property (retain) FBFetcher *facebookFetcher;
#end
In the FBFetcher.m:
#implementation FBFetcher
#synthesize facebookFetcher,facebook;
-(void)login{
facebook = [[Facebook alloc] initWithAppId:#"...."];
NSArray *permissions = [[NSArray arrayWithObjects: #"offline_access",#"user_about_me", nil] retain];
[facebook authorize:permissions delegate:self];
}
-(void)fbDidLogin {
NSLog(#"Erfolgreich eingeloggt....");
}
#end
In my app delegate:
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [[[controller facebookFetcher] facebook] handleOpenURL:url];
}
I have a separate view controller with n action tied to a UIButton:
facebookFetcher = [[FBFetcher alloc] init];
[facebookFetcher login];
I can access the login and authorization page, however the method fbDidLogin never gets called. Any suggestions?
The method never gets called because when you authorize, you are doing it in Safari. To take care of this, which I think is a bug from Facebook SDK by the way, open the facebook.m file and find the following line:
[self authorizeWithFBAppAuth:YES safariAuth:YES];
and change it to
[self authorizeWithFBAppAuth:NO safariAuth:NO];
This way you will never be sent to Safari, but everything will be done in a dialog.
Just test it and you'll see that the fbDidLogin method will get called.
Hope it will help
What about
- (void)fbDidNotLogin:(BOOL)cancelled
Does that get called?
Look for this function in Facebook.m. This is where Facebook calls your fbDidLogin function. First make sure this is being called, then debug into it. Make sure you've spelled/defined fbDidLogin correctly in your session delegate (no parameters). If not the respondsToSelector will fail and never call your delegate's function.
- (void)fbDialogLogin:(NSString *)token expirationDate:(NSDate *)expirationDate
{
self.accessToken = token;
self.expirationDate = expirationDate;
if ([self.sessionDelegate respondsToSelector:#selector(fbDidLogin)])
{
[_sessionDelegate fbDidLogin];
}
}

How to handle a custom URL in an already-open app?

I have an app based on the Utility template (i.e. Main and Flip view controllers). The Flip view allows selecting a certain item to be used on the main view. So far - works great.
Now I tried adding a custom URL. Something to the effect of: myapp://itemID=40 that will basically tell the main view: "no need to flip - you'll be dealing with item 40".
I registered the URL type scheme as "myapp" and added the following method to the app delegate:
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
if (!url) {
return NO;
}
NSString *urlString = [url absoluteString];
NSLog(#"URL received: %#", urlString);
NSString *itemID = [urlString stringByReplacingOccurrencesOfString:#"myapp://itemID=" withString:#""];
NSLog(#"Item received: %#", itemID);
[_mainViewController setStartupItem:itemID];
return YES;
}
As you can see, the itemID is set to a property called startupItem in the mainViewController.
I then added one line to the regular application method to verify that startupItem will be nil in case of no URL:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//Make sure URL string is empty
[_mainViewController setStartupItem:nil];
// Override point for customization after application launch.
// Add the main view controller's view to the window and display.
self.window.rootViewController = self.mainViewController;
[self.window makeKeyAndVisible];
return YES;
}
And in MainViewController.m I added code to handle the item to the viewDidLoad event.
And here's my problem: this scheme works great if the app is started from a URL the first time. If it's already running, then we never reach viewDidLoad again and therefore don't handle that particular item, but go on as if none was passed.
My humble question is: which UIViewController should I put my handling code in? Or, am I approaching all this the wrong way? Should this be handled in my model?
As always, thanks in advance for your time!
Guy
I would take a look at the docs for UIApplicationDelegate protocol, specifically;
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
And this which is deprecated.
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
Well definitely not in a method that gets called only once while the application starts up! You need to refactor the item handling code in its own method, then call this method from viewDidLoad (once during startup) and handleOpenURL each time it gets called.

Apple Push Notification Service using Urban Airship in iPhone

I have implemented Apple Push Notification service using Urban Airship and successfully received the notification in my application. If i receive the notification the alert view comes, If i click the view button in alert view, it goes to start the application. Generally it happens in APNS. But my client wants, If any updates happened in the RSS feed and alert view comes, If we click the view in alert view, it should go to the particular feed in the application, doesn't start the application. SO is it possible to do that?. Is any possible to write the events for the particular alert view buttons in my application.
Here my sample code is,
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
[[UIApplication sharedApplication] registerForRemoteNotificationTypes: UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert];
[window addSubview:viewcontrollers.view];
[window makeKeyAndVisible];
NSLog(#"remote notification2: %#",[launchOptions description]);
return YES;
}
In this method didFinishLaunchingWithOptions, i cant get the dictionary values and it always get the Null Value. Is any possible to get the dictionary value in this method(Notification comes).
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
NSString *message = [userInfo descriptionWithLocale:nil indent: 1];
NSLog(#"The message string is %#",message);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle: #"Remote Notification" message: message delegate: nil cancelButtonTitle: #"ok" otherButtonTitles: nil];
[alert show];
[alert release];
}
In this method, i could get the dictionary value. But this method calls only,if any update happens while running in the application.
Please guide me!
Thanks
It is indeed possible to do that. In your application:didReceiveRemoteNotification method you'll be passed an NSDictionary with all of the push notification's data. What you'll want to do is send some ID or URL in the payload to Urban Airship. Something like:
{
"aps": {
"alert": "New RSS entry"
},
"entry_id": "XYZ123"
}
And then you can write code to go and fetch the proper feed entry in your application.
When the application isn't running or has been terminated by the system and the app is launched via the notification:
In this case you have to get the notification dictionary (which is itself a value of the launchOptions):
http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/Reference/Reference.html#//apple_ref/doc/uid/TP40006786-CH3-SW18
I imagine the code would be something like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
NSDictionary *remoteNotification = (NSDictionary *) [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (remoteNotification != nil) {
NSString *message = [remoteNotification descriptionWithLocale:nil indent: 1];
}
}