Graph API with App Token for Page not working - ios

I'm developing an app with Login with Facebook and also Login with username and password.
Now i want to find all the events of a public page on Facebook for both the types of users (Facebook and Normal).
The problem is that the User with Facebook can retrieve the data, but the "normal" user cannot because data is nil.
The steps are :
1 - Compile this url with the correct credential of my Facebook App :
https://graph.facebook.com/oauth/access_token?client_id=APP_ID&client_secret=APP_SECRET&grant_type=client_credentials
2 - Put the url in my browser and retrieve the App Token In the format :
53682XXXXXXXXXX|w6F3Ic6L48XXXXXXXXXXXXXXXXX
3 - Use this piece of code :
NSString *token = [[[FBSession activeSession] accessTokenData] accessToken];
NSString *urlString;
if (!userWithFb) {
NSString *token = #"53682XXXXXXXXXX|w6F3Ic6L48XXXXXXXXXXXXXXXXX";
urlString = [NSString stringWithFormat:#"https://graph.facebook.com/%#/events?access_token=%#", pageId,token];
}else{
urlString = [NSString stringWithFormat:#"https://graph.facebook.com/%#/events?access_token=%#", pageId,token];
}
NSData* data = [NSData dataWithContentsOfURL:[NSURL URLWithString:urlString]];
if(data != nil)
[self performSelectorOnMainThread:#selector(fetchedData:)
withObject:data waitUntilDone:YES];
BUT the data for the normal user is nil. When I put the "urlstring" in my browser I see all the data , I don't know where is the problem. Waiting for solution I say thanks.

I solved my question by adding this piece of code after the if statement :
NSString *encodedURLString = [urlString stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
url = [NSURL URLWithString:encodedURLString];
NSData* data = [NSData dataWithContentsOfURL:url];
The Problem is the "|" in the token, it must be replaced with "&".
Hope this help you !

Related

Second Api call is slowing down app ios

I am using google places api to search for nearby places. I make one call to get the places, and another call to get the phone number of the places. The second call is slowing down the app. Any way around this? If some sample code could be provided as well that would be great.
s1 = [NSString stringWithFormat:#"https://api.foursquare.com/v2/venues/explore?client_id=%#&client_secret=%#&query=%#&v=20201212&m=swarm&sortByDistance=%i&radius=%f&limit=%#&ll=%f,%f", kClientID, kClientSecret, Name, sortByDistance, meterRadius, recorddisplay, lat, lng];
NSLog(#"This is the foursqaure query: %#", s1);
NSURL *jsonURL = [NSURL URLWithString:[self urlEncodeValue:s1]];
NSString *jsonDataString = [[NSString alloc]initWithContentsOfURL:jsonURL];
NSData *jsonData = [jsonDataString dataUsingEncoding:NSUTF8StringEncoding];
//NSLog(#"This is JSON data: %#", jsonDataString);
if(jsonData == nil)
{
NSLog(#"SEARCH RESULT IS NIL.....");
//[pool release];
return FALSE;
}
else
{
//retrieve the objects in the JSON and then make another http request...
}
This line is wrong:
NSString *jsonDataString = [[NSString alloc]initWithContentsOfURL:jsonURL];
You are networking synchronously on the main thread. Never never never do that. That's the cause of the delay.

How can i get the response when i am submiting a form in UIWebView?

As I am implementing a Webpage load in the UIWebView ,where the user has to fill the form and have to click the submit button. During submitting the request I am sending a return url to webpage along with the request.Once the request validates at the website end if return back to my return url.along with this it is sending some parameters.
It is successfully happening,but i am not getting that parameters.How can i get those parameters.
I have implemented the delegate method,but is not giving the parameters.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
Any help greatly appreciated.
I have been in the same Problem ,As iOS webview is not have as much functionality like in the android ,as in android there is JavaScriptInterface.But there is a method in iOS to execute the JS that is stringByEvaluatingJavaScriptFromString.
As you mention you are getting the parameters on the return url then your web developer have to get that parameters(i don't know how he will do ,but my developer did this and converted all the parameters in string) and to store in string parameter.then you can get that value using a JS Function.
NSURL *requestURL = [self.WebView.request URL];
NSLog(#"Reuest URl here is:%#",requestURL);
NSString *javaScript = [NSString stringWithFormat:#"function givResponse(){var x=document.getElementById('div-id').innerHTML;return x; } givResponse(); "];
NSString *jsonString = [self.webView stringByEvaluatingJavaScriptFromString:javaScript];
NSLog(#"The returned value is %#",jsonString);
/* Converting the string to JSON */
NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(#"Here the JSon String from the respose is :%#",json);

Display User Profile Picture from Salesforce in iOS App

I am trying to display logged in user's profile picture using following:
NSLog(#"url is : %#",[SFAccountManager sharedInstance].idData.pictureUrl);
profilePicData=[NSData dataWithContentsOfURL:[SFAccountManager sharedInstance].idData.pictureUrl];
if ( profilePicData )
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/%#", documentsDirectory,#"filename.jpg"];
NSLog(#"pic path: %#",filePath);
[profilePicData writeToFile:filePath atomically:YES];
}
NSLog(#"pic data: %#",profilePicData);
}
in NSLog("%#", [NSData dataWithContentsOfURL:[SFAccountManager sharedInstance].idData.pictureUrl]); shows some data but does not display picture in UIImageView.
Any Help would be appreciated .
I was attempting to do exactly the same inside the Chatter API - I wanted to load image from feed data under "smallPhotoUrl". What I have discovered is, that at the end of URL active token has to be added.
This source introduced me to concept: Accessing Chatter user pics
And I finally was able to find some clear information how to access that token here: salesforce_platform_mobile_services.pdf page 262
So eventually I did this:
NSString *builtImageUrlWithToken = [NSString stringWithFormat:#"%#?oauth_token=%#",
phototoUrl, [SFAccountManager sharedInstance].credentials.accessToken];
NSURL *imageURL = [NSURL URLWithString:builtImageUrlWithToken];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
I think it's relevant to this topic, as I came across it while looking for this particular solution. I am sure it could be useful for others as well.
Thanks!
First Apple docs say not to use dataWithContentsOfURL for network calls, because it is synchronous.
So, you can do something like this instead to get the image:
SFIdentityData *idData = [SFAccountManager sharedInstance].idData;
if(idData != nil) {
SFRestRequest *request = [[SFRestRequest alloc] init];
request.endpoint = [idData.pictureUrl absoluteString];
request.method = SFRestMethodGET;
request.path = #"";
[[SFRestAPI sharedInstance] send:request delegate:_delegate];
}
(This is async. You could use blocks instead of delegation.)
In your delegate you can (for example) store the image in CoreData or assign the NSData to a UIImage thus:
[[UIImage alloc] initWithData:picData];
You do also need to make sure that your UIImage is properly wired up, e.g. one way would be through a UIImageView that's an IBOutlet.
Calling salesforce Rest API and getting user information .
NSString *path=#"/services/data/v29.0/chatter/users/me";
SFRestMethod method=0;
SFRestRequest *request = [SFRestRequest requestWithMethod:method path:path queryParams:queryParams];
[[SFRestAPI sharedInstance] send:request delegate:self];
this will return json response.
- (void)request:(SFRestRequest *)request didLoadResponse:(id)dataResponse {….}
Parse required photo dictionary from it and use fullEmailPhotoUrl to load/save images.
using largePhotoUrl and largePhotoUrl did not load picture for me.
Eg. of photo dictionary parsed:
photo = {
fullEmailPhotoUrl = "https://na14.salesforce.com/ncsphoto/<SOMEIDENTIFIERS>";
largePhotoUrl = "https://c.na14.content.force.com/profilephoto/<SOMEIDENTIFIERS>/F";
photoVersionId = <PHOTOID>;
smallPhotoUrl = "https://c.na14.content.force.com/profilephoto/<SOMEIDENTIFIERS>/T";
standardEmailPhotoUrl = "https://na14.salesforce.com/ncsphoto/<SOMEIDENTIFIERS>";
url = "/services/data/v29.0/chatter/users/<SOMEIDENTIFIERS>/photo";
};
In swift 3, Using Alamofire:
if let url = URL(string: baseURl + "/sobjects/Attachment/\(imageID)/Body"){
let header = ["Authorization": "Your Auth Token"]
Alamofire.request(url, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: header).responseData { (response) in
if response.error == nil {
// Show the downloaded image:
if let data = response.data {
self.profileImg.image = UIImage(data: data)
}
}
}
}

UIWebView remember usernam and password ,an autofill it [duplicate]

I'm building an iPhone app that is just a UIWebView of an existing mobile site that has a form-based login. When I login to the mobile site on iPhone Safari, I'm prompted to save my username/password, and it's then autofilled when I go back to the site later.
I'd like to enable the same functionality in the UIWebView, but for the life of me, I can't figure out how to do it. Any ideas?
Solution
Following Michael's basic model (see accepted answer), I was able to get this done. Here's what I did:
SETTING DATA
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType; {
//save form data
if(navigationType == UIWebViewNavigationTypeFormSubmitted) {
//grab the data from the page
NSString *username = [self.webView stringByEvaluatingJavaScriptFromString: #"document.myForm.username.value"];
NSString *password = [self.webView stringByEvaluatingJavaScriptFromString: #"document.myForm.password.value"];
//store values locally
[[NSUserDefaults standardUserDefaults] setObject:username forKey:#"username"];
[SFHFKeychainUtils storeUsername:username andPassword:password forServiceName:#"MyService" updateExisting:YES error:nil];
}
}
GETTING DATA
- (void)webViewDidFinishLoad:(UIWebView *)webView{
//verify view is on the login page of the site (simplified)
NSURL *requestURL = [self.webView.request URL];
if ([requestURL.host isEqualToString:#"www.mydomain.com"]) {
//check for stored login credentials
NSString *username = [[NSUserDefaults standardUserDefaults] objectForKey:#"username"];
if (username.length != 0 ) {
//create js strings
NSString *loadUsernameJS = [NSString stringWithFormat:#"document.myForm.username.value ='%#'", username];
NSString *password = [SFHFKeychainUtils getPasswordForUsername: username andServiceName:#"MyService" error:nil];
if (password.length == 0 ) password = #"";
NSString *loadPasswordJS = [NSString stringWithFormat:#"document.myForm.password.value ='%#'", password];
//autofill the form
[self.webView stringByEvaluatingJavaScriptFromString: loadUsernameJS];
[self.webView stringByEvaluatingJavaScriptFromString: loadPasswordJS];
}
}
}
Note that I'm using Buzz Andersen's awesome SFHFKeychainUtils package to store sensitive data to the iOs Keychain.
In order to get SFHFKeychainUtils working, you need to do a few things:
Add SFHFKeychainUtils.h and SFHFKeychainUtils.m to your project
Add the Security.framework to your project
#import <Security/Security.h> and #import "SFHFKeychainUtils.h"
From my looking I don't think there is an easy way to do it. Here is an idea of what might work though:
create your uiwebview
create a nsurlrequest
after your webview delegate page loaded function fires look in the request's http body
find the form for login (regex for common login forms?)
retrieve give the user the option to save it and then retrieve later

Using NSURLCredentialPersistenceForSession while request and then clearing the credentials on logout still persist the cerdentials

I am using NSURLCredentialPersistenceForSession within didReceiveAuthenticationChallenge of NSURLConnection delegate method while login.
Now when I logout and use this code for clearing the storage..
NSURLCredentialStorage *credentialStorage = [NSURLCredentialStorage sharedCredentialStorage];
NSDictionary *credentialsDicationary = [credentialStorage allCredentials];
NSLog(#"credentialsDicationary..%#",[credentialsDicationary description]);
for (NSURLProtectionSpace *space in [credentialsDicationary allKeys]) {
NSDictionary *spaceDictionary = [credentialsDicationary objectForKey:space];
NSLog(#"spaceDictionary..%#",[spaceDictionary description]);
for (id userName in [spaceDictionary allKeys]) {
NSURLCredential *credential = [spaceDictionary objectForKey:userName];
[credentialStorage removeCredential:credential forProtectionSpace:space];
}
}
But when I suddenly login again exactly after logout the login happens with wrong credentials. Please let mw know how to clear the cache. It works if I relogin after some 5 secs of time.
Thanks in advance..
AJ
If you're using NSURLSession, invalidate the session and create a new one, e.g.:
[self.session invalidateAndCancel];
self.session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil];
This will clear session-scoped credentials.
If you use NSURLCredentialPersistenceForSession to create the credential then the app stores the credential for the entire session until the app is closed.
You can work around this by either:
changing the url (like appending '#' to the end of the url)
Use NSURLCredentialPersistenceNone and provide the credentials with each nsurlrequest
Append auth info to the url (http://username:password#mywebsite.com), instead of using creds
Append auth info to the request header, instead of using creds
//Pseudo code for appending to header:
NSString *authString = [NSString stringWithFormat:#"%#:%#", self.loginCreds.username, self.loginCreds.password];
NSData *stringData = [authString dataUsingEncoding:NSUTF8StringEncoding];
authString = [NSString stringWithFormat:#"Basic %#", [stringData base64EncodedString]];
[[self requestHeader] setValue:authString forHTTPHeaderField:#"Authorization"];
It's possible to remove the credential but it can take minutes before it is actually removed. However, I don't remember how its done.. It's either done the way you mentioned in the question or through the keychain.
I had the same issue and I tried clear the credential storage, cookies associated with url and even trying to reset the session but nothing seemed to work, finally I just resorted to adding a a random query string value to the end of the url and that did the trick for me
// Random number calculated.
NSInteger randomNumber = arc4random() % 16;
NSURL* apiURL = [NSURL URLWithString:#"https://localhost/api/"];
[[RKObjectManager sharedManager] getObjectsAtPath:[NSString stringWithFormat:#"%#getUser?randomNumber=%d",apiURL,randomNumber]
parameters:nil
success:successBlock
failure:failureBlock];
So instead of trying to remove current cached credentials (which seemed impossible) just use a "fresh" url so there aren't any cached objects associated with it.
I was facing the same problem, now it works.
Using NSURLConnection this issue can be fixed easily by adding a random number to the end of the URL:
So, search for your URLRequest and append the random number to URLRequest
NSInteger randomNumber = arc4random() % 999;
NSString *requestURL = [NSString stringWithFormat:#"%#?cache=%ld",yourURL,(long)randomNumber];
NSURL *URLRequest = [NSURL URLWithString:requestURL];
And make sure you have a random number at the end of all URLs you are calling.

Resources