I have a popular medicine app often used by med students and residents at the bedside. I incorporated the new FB SKD into my last updated which, when opened for the first time (and subsequently if not used for a few days), opens the native FB app then redirects to my app. Many customers have complained because the info within the app often needs to be looked up quickly (crashing patient).
Is it possible to set up my app so the user needs to click on a button within the app before connecting to FB? Thanks!
I think you will need to make change to authorizeWithFBAppAuth method in facebook.m file of the SDK.
This SO has a suggestion for you.
When you download the FB SDK you get a sample project. Compile and run it, and you should see a toggle button that allows user to login/logout. You've got the FB official images in that project, and the code behind it is pretty simple:
/**
* Called on a login/logout button click.
*/
- (void)fbButtonClick:(id)sender {
if (fbButton.isLoggedIn) {
[self logout];
} else {
[self login];
}
}
/**
* Show the authorization dialog.
*/
- (void)login {
[_facebook authorize:nil delegate:self];
NSLog(#"Sas");
}
/**
* Invalidate the access token and clear the cookie.
*/
- (void)logout {
[_facebook logout:self];
}
You should also change the button's state in the FBAuth delegate methods (which you've already implemented) by calling a method similar to this one:
- (void)updateFbButtonAccordingToSessionStatus {
//Check if session is valid and update button accordingly
if ([self.facebook isSessionValid] == NO ) {
fbButton.isLoggedIn = NO;
[fbButton updateImage];
}
else {
fbButton.isLoggedIn = YES;
[fbButton updateImage];
}
}
Hope this helps.
Related
Is there a way to tell if an iOS app enters the foreground from fast-app switching or manually? I need to know by the time applicationWillEnterForeground is called, so some specific code can be executed (or not executed) depending on the condition in which the app entered the foreground.
EDIT:
It turned out that this was more of a design issue for me. I moved my code to applicationDidBecomeActive. I also added a BOOL property to the appDelegate called fastAppSwitching (probably the wrong name for it). I set this to YES in application:handleOpenURL and application:openURL:sourceApplication:annotation. Then I added the following code to application:didFinishLaunchingWithOptions:
if (launchOptions) {
self.fastAppSwitching = YES;
}
else {
self.fastAppSwitching = NO;
}
In applicationDidBecomeActive, I used the following code:
if (fastAppSwitching == YES) {
self.fastAppSwitching = NO; //stop, don't go any further
}
else {
...
}
EDIT2: MaxGabriel makes a good point below: "Just a warning to others taking the solution described here, applicationDidBecomeActive: is called when the user e.g. ignores a phone call or text message, unlike applicationWillEnterForeground". This is actually also true for in-app purchases and Facebook in-app authorization (new in iOS 6). So, with some further testing, this is the current solution:
Add a new Bool called passedThroughWillEnterForeground.
In applicationWillResignActive:
self.passedThroughWillEnterForeground = NO;
In applicationDidEnterBackground:
self.passedThroughWillEnterForeground = NO;
In applicationWillEnterForeground:
self.passedThroughWillEnterForeground = YES;
In applicationDidBecomeActive:
if (passedThroughWillEnterForeground) {
//we are NOT returning from 6.0 (in-app) authorization dialog or in-app purchase dialog, etc
//do nothing with this BOOL - just reset it
self.passedThroughWillEnterForeground = NO;
}
else {
//we ARE returning from 6.0 (in-app) authorization dialog or in-app purchase dialog - IE
//This is the same as fast-app switching in our book, so let's keep it simple and use this to set that
self.fastAppSwitching = YES;
}
if (fastAppSwitching == YES) {
self.fastAppSwitching = NO;
}
else {
...
}
EDIT3: I think we also need a bool to tell if app was launched from terminated.
If your application is launched by another application, the
- (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
sourceApplicarion:(NSString *)bundleID
annotation:(id)info;
method is called on your app delegate. You can use this method to e. g. set a Boolean switch to true that indicates whether the app was launched by another program.
The peoblem is that this method is called after applicationWillEnterForeground:, so you can't tell in that method whether your app was launched manually or automatically.
However, I suspect that if you need this to be detected in a particular method, you may have a design problem and you should probably reorganize your code.
In the case where your app is opened from another app, application:openURL:sourceApplication:annotation will be called on your app delegate.
I am really struggling with game center right now. It could be because GK as a whole has been pooping out all day (letterpress was just released!), but I can't get an auth dialog to come up:
- (void) authenticateLocalPlayer
{
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error) {
if (viewController) {
NSLog(#"Foo 1");
[self presentViewController:viewController animated:YES completion:nil];
} else if (localPlayer.isAuthenticated) {
NSLog(#"Foo 2");
} else {
NSLog(#"Foo 3");
}
};
}
This method is hooked up to a button. When I press it, I get this in the console:
<Info>: 23:41:52.226407 com.apple.AVConference: GKSConnSettings: set server: {
"gk-cdx" = "17.173.254.218:4398";
"gk-commnat-cohort" = "17.173.254.220:16386";
"gk-commnat-main0" = "17.173.254.219:16384";
"gk-commnat-main1" = "17.173.254.219:16385";
}
Only the third option is being printed out: Foo 3. I am going nuts here. What is going on?
Doh!
I forgot that I had switched out bundle identifiers for temporary testing on my device.
You need to use the bundle identifier as specified in ITC.
Another reason you might be seeing this even when your bundle ID is correct and you are sure everything is okay with your app info on iTunes Connect could be that you are logged into a real GameCenter account instead of a sandbox account. If so, log out of GameCenter by clicking on your email and selected to 'Sign Out' then log in to one of your test accounts (set up in iTunes Connect in the 'Manage Users' section). You'll have to accept the GameCenter Sandbox terms of service (it took a moment for these terms to appear for me so be patient). Once you have done so and have logged in with a sandbox account the GameCenter dialog should start showing up!
I'm trying to implement the native facebook share for iOS 6 and need check if a share did succeed or not. This is the code I have used:
BOOL displayedNativeDialog =
[FBNativeDialogs
presentShareDialogModallyFrom:delegate
initialText:#"test"
image:nil
url:nil
handler:^(FBNativeDialogResult result, NSError *error) {
if (error) {
/* handle failure */
NSLog(#"error:%#, %#", error, [error localizedDescription]);
} else {
if (result == FBNativeDialogResultSucceeded) {
/* handle success */
NSLog(#"handle success");
} else {
/* handle user cancel */
NSLog(#"user cancel");
}
}
}];
if (!displayedNativeDialog) {
/* handle fallback to native dialog */
}
My problem is when I try this with no internet connection available I still get the FBNativeDialogResultSucceeded
It looks like you should get an error when no internet connection is available but it seems that it doesn't work like that.
If there are some solution where I don't need to use the reachability SDK that would be great.
You'll likely have to use the reachability SDK at this point. The Facebook SDK builds on top of the SLComposeViewController for the native functionality. That view controller returns two possible choices:
SLComposeViewControllerResultCancelled
SLComposeViewControllerResultDone
SLComposeViewControllerResultDone: The view controller is dismissed and the message is being sent in the background. This occurs when the user selects Done.
So since Facebook mirrors this the success case means the user clicked done and the message has been sent in the background.
However if you run this and there is no internet connection, the user should still see a pop-up indicating that the post could not be sent due to a connection failure.
is there a way to track the user-input to a uiwebview?
In my case the user must fill out several folders in the webpage (Login form). However, the input (strings) should then be handeled by / stored in the app. (App should remember login-info and do login next time automatically)
Thanks for help
Yes you can do this. Implement
– webView:shouldStartLoadWithRequest:navigationType:
This delegate . This method gets called whenever your webview is about to make a request. So now when someone clicks a button on your webpage, you will get a call to this method. After you catch this call, you can choose to do whatever you want with it. Like redirect the link through your own servers, or log a request to your server about user activity etc.
Example - here you are trying to intercept any links clicked on your webpage & pass it through myMethodAction first.
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
{
if(navigationType == UIWebViewNavigationTypeLinkClicked)
{
if(overrideLinksSwitch.on == TRUE)
{
[self myMethodAction];
[myWebView stopLoading];
return YES;
}
else
{
return YES;
}
}
return YES;
}
Hope this helps...
I have an app that I want to be able to connect to Facebook and post to the user's wall. I have the following code:
- (void)viewDidLoad {
static NSString* kApiKey = #"PRIVATE";
static NSString* kApiSecret = #"PRIVATE";
_session = [[FBSession sessionForApplication:kApiKey secret:kApiSecret delegate:self] retain];
// Load a previous session from disk if available. Note this will call session:didLogin if a valid session exists.
[_session resume];
// Set these values from your application page on http://www.facebook.com/developers
// Keep in mind that this method is not as secure as using the sessionForApplication:getSessionProxy:delegate method!
// These values are from a dummy facebook app I made called MyGrades - feel free to play around!
[super viewDidLoad];
}
- (IBAction)postGradesTapped:(id)sender {
_posting = YES;
// If we're not logged in, log in first...
if (![_session isConnected]) {
self.loginDialog = nil;
_loginDialog = [[FBLoginDialog alloc] init];
[_loginDialog show];
}
// If we have a session and a name, post to the wall!
else if (_facebookName != nil) {
[self postToWall];
}
// Otherwise, we don't have a name yet, just wait for that to come through.
}
The problem I have is that when the user clicks the button associated with the IBAction it will pop up the login dialog, but then the window disappears without ever pulling up the Publish Story to Wall dialog. How do I get it to login and then pull up the Publish Story to Wall?
I think you may need to use FBPermissionDialog to ask for "post to wall" permission first (I'm not sure what the exact string is; it might be in the examples).
Also note that "FBSession" is the old "iPhone" SDK (last updated in April); there's a newer "iOS" SDK at http://github.com/facebook/facebook-ios-sdk
I once encountered this behavior when my Security Key was wrong (in the new API you don't need it, but if you're based on old API it still requires it).
Make sure you use "App Id" and "App Secret" from the Facebook app control page. (And not "API Key")
Good luck!