As you know, you can display some facebook views to make some operations, like app requests, post etc. There is a delegate to manage the callbacks like : dialogDidComplete:, dialogDidNotComplete:. The view is like that :
But there is not differentiation between the cancel and share button. You will have the same callback in dialogDidComplete:. The only way to manage a cancelation is the little cross in the corner.
In my case I would like to do some operations if the user pressed share and not when he pressed Cancel.
The private social network Path manage this case and I'm wondering how ?
Do you guys have some ideas ?
If I am not wrong:
if you press Share you get a requestID back as part of the returned URL
if you press Cancel you are returned into dialogDidComplete but it does not return a requestID back as part of the returned URL.
Code:
- (void)dialogCompleteWithUrl:(NSURL *)url {
if (![url query]) {
NSLog(#"User canceled dialog or there was an error");
return;
}
}
Related
I am trying to get a callback or notification if a user clicked on a "call" or "cancel" button when trying to call a phone number from the app. I use the following code:
guard let url = URL(string: "tel://\(number)") else { return }
UIApplication.shared.open(url, options: [:]) { didCall in
print(didCall)
}
Issue with this callback is that it is triggered when the dialog appears not when I click any of the buttons and it is always true. I couldn't find another solution. I know that since iOS 10 there's a notification I can subscribe to to get information if user clicked "Allow" or "Don't allow" notifications but similar thing doesn't seem to exist for call action.
The docs state that the prompt will always appear when calling tel but since the prompt is made outside of your app, you can't do anything to observe it.
Apple's documentation is clear on using SLComposeViewController to provide sharing capabilites with other social networks such as Twitter and Facebook.
Typical code will use isAvailableForServiceType to verify if a particular service is available and then add a completion handler to the view controller where an SLComposeViewControllerResult can be checked for either SLComposeViewControllerResultCancelled or SLComposeViewControllerResultDone, which check if the user tapped on the 'Post' button or on the 'Cancel' button after the sharing view has been displayed.
The issue here is that if you use SLComposeViewControllerResultDone to validate that the user made the request, you don't actually check if it was successful such as when the user has limited or no connectivity.
I have tried with one of my apps to test this and have noticed that the SLComposeViewControllerResultDone constant is still valid even if airplane mode is turned on such that a request is not possible. What this means is that the user fills out the sharing view fields and taps on 'Post' and my success code executes even though I should really be checking to make sure that the post was indeed successful.
Currently, I figure that the best option is to check for an Internet connection using the standard Reachability options (as recommended here) and disable the sharing button if a connection is not available, but I'm not sure if this is the best solution as it doesn't account for a limited connection where the user can tap on 'Post' but the actual request is unsuccessful.
My question is what is the best method of detecting if a sharing request has successfully completed?
then you need to make sure that you do not write below line in didSelectPost
[self.extensionContext completeRequestReturningItems:nil completionHandler:nil];
and once you get success or fail based on that in the your request handler you can write above line, so your didSelectPost should be like :
- (void)didSelectPost {
NSExtensionItem *inputItem = self.extensionContext.inputItems.firstObject;
NSItemProvider *attachment = inputItem.attachments.firstObject;
if ([attachment hasItemConformingToTypeIdentifier:#"public.url"])
{
//NSString *strLink = [attachement loadItemForTypeIdentifier:#"public.url" options:nil completionHandler:nil];
[attachment loadItemForTypeIdentifier: #"public.url"
options: nil
// make your request here
}];
}
}
I'm implementing OAuth login using Facebook SDK, but the FBSession.openActiveSessionWithReadPermissions:allowLoginUI:completionHandler method is not calling the completionHandler nor is it returning "true", which would indicate a cached token. Everything else seems to work fine, except this. What's wrong with this code?
var completionHandler: FBSessionStateHandler = {
session, status, error in
NSLog("token not cached");
if error {
// Login failed for some reason, so we notify the delegate.
self.delegate.didFailOpenningSession?(self, withError: ErrorUtility.error(
code: .FailedOpenningSession,
withFacebookError: error
));
// Don't proceed on errors
return;
}
// Session is now open, we should notify the delegate
self.delegate.didOpenSession?(self);
};
NSLog("here");
// Open the session, prompting the user if necessary. This might send the application to the background
if FBSession.openActiveSessionWithReadPermissions(["public_profile"], allowLoginUI: true, completionHandler: completionHandler) {
NSLog("Token cached");
// If we end up here, the session token must exist, so we now have an open session
self.delegate.didOpenSession?(self);
}
Edit: I forgot to mention that the NSLog logs "here", but not "Token cached" nor "token not cached"
Edit: Now things got a bit stranger. When my app launches I show a screen with a Facebook login button. When the user presses the button the code above gets triggered. After I authorise the app, the app gets back to the same screen (it shouldn't, but I can't do it any other way until the completion handler gets called). Then I tried pressing the button again and now I do get the logs.
This is what I get:
here
token not cached
here
The first line is from the first button press, the other two appear when I press it the second time. Now what's so odd about it? Shouldn't "token not cached" and "here" be reversed??? Is it calling the competionHandler from the last call or something?
Nevermind, that much is fixed.
Edit: one other thing. If I press the button multiple times, I always get "token not cached". I think it should be caching
It's solved. I was missing the method AppDelegate.application:handleOpenURL -> Bool
First ensure that you are using correct closure syntax. You are not providing a matching closure callback for the block callback.
notice the block callback for the FB session is:
^(FBSession *session,
FBSessionState state, NSError *error)
You should have
/*function parameters*/){ session, state, error in
//closure declaration goes at the top after the {
//Insert logic here
NSLog("Token cached");
}
This will equate to
FBSession.openActiveSessionWithReadPermissions(permissions, allowLoginUI:true){ session, state, error in
//callback code body here
}
This usually because of missing handle seesion in app’s application:openURL function.
It is in AppDelegate.m. Description from facebook samples says below:
// During the Facebook login flow, your app passes control to the Facebook iOS app or Facebook in a mobile browser.
// After authentication, your app will be called back with the session information.
// Override application:openURL:sourceApplication:annotation to call the FBsession object that handles the incoming URL
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation
{
return [FBSession.activeSession handleOpenURL:url];
}
I've done a google plus integration and i've done a simple login and displaying google friends on table. But the problem is before I load the friends I want to check if the user is logged in, so in my friendsdisplayViewController i've done something like this
if ([GPPSignIn sharedInstance].authentication)
{
NSLog(#"Status is authenticated, fetching friends!!");
[self fetchGooglePlusFriends:kGTLPlusCollectionVisible];
}
else
{
[[GPPSignIn sharedInstance]authenticate];
}
I've defined the callback function one on initial signupviewcontroller and one under this one
-(void)finishedWithAuth:(GTMOAuth2Authentication *)auth error:(NSError *)error
{
//code
}
But whenever the else case executes it always calls the call back function defined on signupviewcontroller not the one I defined on friendsdisplayViewController hence I'm unable to display the list and but able to validate the authentication.
I'm just curious how the call to this google call back function (finishedWithAuth) is made. Why did it call the one in signup and not in friendsdisplay eventhough the authentication was triggered from friendsdisplay.
I figured out the issue was because of the delegate which needs to be put on every view controller which you are calling, the GPPSignInDelegate. And the finishedWithAuth will then get triggered from the ViewController which you are trying to call it else it will trigger the finishedWithAuth in the ViewController which is standing in top of stack.
I have a set of links (add to wishlist) with click event . The click event checks if the user is logged in (ajax request) and depending on the result the click continues. In the case the user is not logged in I have a generic jQuery UI modal dialog that the user can use to log in.
That all works well but I would like to extend the functionality to be able to continue with click of the links after the user logs in using the dialog.
ie. CLICK ADD TO WISHLIST -> LOGGED IN ?
YES -> CONTINUE LINK CLICK (add to wishlist)
NO -> SHOW LOGIN DIALOG ->
USER SUBMITS CREDENTIALS -> LOGGED IN?
YES => CONTINUE LINK CLICK (add to
wishlist)
NO => SHOW LOGIN ERROR
Of course I do not want to perform any postbacks, all through ajax and jquery.
Thanks
You could pass the url of the click action to the login modal and redirect after successful login.
Alternativly, if you have set it up to login via AJAX, you could store the click event target and then trigger a click event after a successful login.
Something like the following:
var is_logged_in = false;
$('a.add_to_wishlist').click(function(e) {
if(is_logged_in) {
//do stuff
} else {
show_modal(e.target); //pass the event target to the modal
}
});
function show_modal(trigger) {
//do stuff
is_logged_in = true;
$(trigger).trigger('click');
}
Hopefully this helps.
If you're in control of your server side code then you should place the authentication + save to wish list in the same request.
User clicks add to wish list
Ajax request to add page to wish list is sent to server.
Server check to see if user is logged in.
If the user is logged in: save the item to the wish list and return a success response.
If the user it not logged in: return a failed response.
The ajax response callback should update the UI based on the response.
If you're not in control of your server code then you'll have to make two ajax request if the authentication request is successful.