NSURL *pictureURL = [NSURL URLWithString:[NSString stringWithFormat:#"https://graph.facebook.com/%#/picture?type=large&return_ssl_resources=1", facebookID]];
NSString *urlString = [pictureURL absoluteString];
FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc] initWithGraphPath:#"me" parameters:nil];
[request startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
if (!error) {
// result is a dictionary with the user's Facebook data
NSDictionary *userData = (NSDictionary *)result;
NSString *facebookID = userData[#"id"];
NSURL *pictureURL = [NSURL URLWithString:[NSString stringWithFormat:#"https://graph.facebook.com/%#/picture?type=large&return_ssl_resources=1", facebookID]];
NSString *urlString = [pictureURL absoluteString];
NSLog(#"sting=%#",urlString);
PFUser *me = [PFUser currentUser];
me[#"facebookId"] = userData[#"id"];
me["pictureURL"] = userData[urlString];
me[#"username"] = userData[#"name"];
[me saveInBackgroundWithBlock:^(BOOL succeeded, NSError * _Nullable error) {
if (error) {
NSLog(#"Error to store=%#",error.localizedDescription);
}
}];
[self presentViewController:push animated:YES completion:nil];
} else {
[self presentViewController:push animated:YES completion:nil];
}
}];
I need to store the Facebook Image or URL when any new user login into my app. AFAIK we can't save the url directly so tried to convert it into NSString but then it threw error "'Can't use nil for keys or values on PFObject. Use NSNull for values.'"
Is there any way so that I can store that link or any other alternate way to save directly the Image into Parse?
Your issue is most likely being caused by the following line:
me["pictureURL"] = userData[urlString];
You most likely want this to be:
me["pictureURL"] = urlString;
As you have it, you will setting me[#"pictureURL"] to nil because you probably don't have a value in userData with a key matching urlString.
Try this, the url should be converted to data then saved as a PFFile.
NSURL *pictureURL = [NSURL URLWithString:[NSString stringWithFormat:#"https://graph.facebook.com/%#/picture? type=large&return_ssl_resources=1", facebookID]];
NSData *data = [NSData contentsOfURL:picureURL];
PFFile *file = [PFFile fileWithData:data];
//save it
[file saveInBackground];
Hope that helps!
Related
I have tried to get friend list from facebook using Graph API but it's not returning friend list. I have tried following code to get list after a successful login in facebook...
FBRequest *req = [FBRequest requestForMe];
[req startWithCompletionHandler:^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *result, NSError *error) {
if (!error)
{
[[VSFacebook sharedFacebook] setFbUser:result];
FriendsViewController *f = [[FriendsViewController alloc] initWithNibName:#"FriendsViewControlleriPad" bundle:nil];
[self presentViewController:f animated:YES completion:nil];
}
}];
and after connecting on FriendsViewContrller.m file I have call graph API to get friend list as following
self.facebookBlock = completionBlock;
NSString *fields = #"id,name,picture,birthday";
NSString *format = #"json";
NSString *urlString = [NSString stringWithFormat:#"https://graph.facebook.com/%#/friends?fields=%#&format=%#&access_token=%#", #"me", fields, format, self.fbAccessTokenData.accessToken];
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLResponse *response = nil;
NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
id result = nil;
if (data)
{
result = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
}
self.facebookBlock([result valueForKey:#"data"], error);
I got on result only three value pair like "summary", "data", "paging"
You cann't get all friends list from facebook using Graph API. It's
not possible to get all Friend's List , according to new API version
In Below code run so i get a response from url but when i try to get encodedPoints it give me a null value. also i update RegexKitLite but prob. not solve. Any suggestion are welcome Thank you advance.
NSString* saddr = [NSString stringWithFormat:#"%f,%f", f.latitude, f.longitude];
NSString* daddr = [NSString stringWithFormat:#"%f,%f", t.latitude, t.longitude];
NSString* apiUrlStr = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=%#&destination=%#&sensor=false", saddr, daddr];
// http://maps.googleapis.com/maps/api/directions/json?origin=41.029598,28.972985&destination=41.033586,28.984546&sensor=false%EF%BB%BF%EF%BB%BF
NSURL *apiUrl = [NSURL URLWithString:[apiUrlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSLog(#"api url: %#", apiUrl);
NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:nil error:nil];
NSString* encodedPoints = [apiResponse stringByMatching:#"points:\\\"([^\\\"]*)\\\"" capture:1L];
NSLog(#"encodedPoints: %#", encodedPoints);
if (encodedPoints) {
return [self decodePolyLine:[encodedPoints mutableCopy]];
}
else {
return NO;
}
I think its not a good way to do API request synchronously, especially when user' phone has poor internet connection, it will slow down the responsiveness of your application. So you should do an asynchronous API request with NSURLSession.
Also, the Directions API might return more than one routes for your request. So its better to use a NSArray to store your polyline points.
Sample code:
- (void)getPolyline {
NSURL *url = [[NSURL alloc] initWithString:#"https://maps.googleapis.com/maps/api/directions/json?origin=Chicago,IL&destination=Los+Angeles,CA&key=YOUR_API_KEY"];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL: url];
NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithRequest:request completionHandler:
^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (!error) {
NSError *jsonError;
NSDictionary *dict = (NSDictionary*)[NSJSONSerialization JSONObjectWithData:data options:nil error:&jsonError];
if (!jsonError) {
NSArray *routesArray = (NSArray*)dict[#"routes"];
NSMutableArray *points = [NSMutableArray array];
for (NSDictionary *route in routesArray) {
NSDictionary *overviewPolyline = route[#"overview_polyline"];
[points addObject:overviewPolyline[#"points"]];
}
NSLog(#"%#", points);
}
} else {
//print error message
NSLog(#"%#", [error localizedDescription]);
}
}] resume];
}
I am using PFLogInViewController to login to facebook which works successfully the first time-
- (void)logInViewController:(PFLogInViewController *)controller
didLogInUser:(PFUser *)user {
if([PFFacebookUtils isLinkedWithUser:user]){
FBRequest *request = [FBRequest requestForMe];
[request startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
NSDictionary *userData = (NSDictionary *)result;
NSString *facebookID = userData[#"id"];
NSString *name = userData[#"name"];
NSString *location = userData[#"location"][#"name"];
NSString *gender = userData[#"gender"];
NSString *birthday = userData[#"birthday"];
NSString *relationship = userData[#"relationship_status"];
[user setObject:userData[#"id"] forKey:#"fbId"];
[user setObject:userData[#"name"] forKey:#"name"];
[user setObject:userData[#"email"] forKey:#"email"];
[user saveInBackground];
NSURL *pictureURL = [NSURL URLWithString:[NSString stringWithFormat:#"https://graph.facebook.com/%#/picture?type=large&return_ssl_resources=1", facebookID]];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:pictureURL];
// Run network request asynchronously
[NSURLConnection sendAsynchronousRequest:urlRequest
queue:[NSOperationQueue mainQueue]
completionHandler:
^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (connectionError == nil && data != nil) {
// Set the image in the header imageView
PFFile *profileImage=[PFFile fileWithData:data];
[user setObject:profileImage forKey:#"profileImage"];
[user saveInBackground];
}
}];
}];
}
[self dismissViewControllerAnimated:YES completion:nil];
}
If I then call [PFUser logOut] and open the PFLogInViewController again, when I tap the facebook icon to log in again, the facebook spinner spins indefinitely and I get the error "Attempted to change an objectId to one that's already known to the OfflineStore."
How do I log out of the current user and then login again using PFLogInViewController?
If I remove [Parse enableLocalDatastore] from the appDelegate, I no longer get this error. If I am not pinning any objects is there any disadvantage to disabling this? Will I still be able to use "saveEventually" if there is no network connection?
I think you are trying to save same object(email) again.
On first login, that email id will be stored fisrt time. But, after logout, you are again trying to store same email.
Try to search that entry is already exists in Parse. If you want to update the other details of user then you can update that using objectId.
Try unlinking the PFUser from the PFFacebookUtils and also close the active Facebook session and clear it's token.
[[FBsession activeSession]closeAndClearTokenInformation];
Hope this helps..
I am downloading a zip, unzipping it, and then attempting to parse and object map data from an xml file included in the zip. I know if the XML file was not in a zip I could do something like
NSURL *URL = [NSURL URLWithString:#"http://restkit.org/articles"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
RKObjectRequestOperation *objectRequestOperation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:#[ responseDescriptor ]];
But because I am download a zip, I have to (or at least I think I have to) use the following code
NSURL *URL = [NSURL URLWithString:#"http://www.mediafire.com/download/6tfd33xkiepx8a3/db_UI.zip"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
self.operation = [[AFHTTPRequestOperation alloc]
initWithRequest:request];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"testDownload"];
self.operation.outputStream = [NSOutputStream outputStreamToFileAtPath:path append:NO];
// Set download completion block
[self.operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"Successfully downloaded file to %#", path);
NSString *zipPath = path;
NSString *destinationPath = [paths objectAtIndex:0];
[SSZipArchive unzipFileAtPath:zipPath toDestination:destinationPath delegate:self];
} failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
// NSLog(#"error: %#", operation.responseString);
}];
// Start download operation
[self.operation start];
[RKMIMETypeSerialization registerClass:[RKXMLReaderSerialization class] forMIMEType:#"application/xml"];
So in this case, how can I use RKObjectMapping. Or is there an alternative?.......
This is from Rest-Kit docs, This parsing JSON object if you can change the MIME Type you can do with XML and what ever
You can find it here: Rest-Kit docs
NSString* JSONString = #"{ \"name\": \"The name\", \"number\": 12345}";
NSString* MIMEType = #"application/json";
NSError* error = nil;
id<RKParser> parser = [[RKParserRegistry sharedRegistry] parserForMIMEType:MIMEType];
id parsedData = [parser objectFromString:JSONString error:&error];
if (parsedData == nil && error) {
// Parser error...
}
RKObjectMappingProvider* mappingProvider = [RKObjectManager sharedManager].mappingProvider;
RKObjectMapper* mapper = [RKObjectMapper mapperWithObject:parsedData mappingProvider:mappingProvider];
RKObjectMappingResult* result = [mapper performMapping];
if (result) {
// Yay! Mapping finished successfully
}
I have a NSDictionary called itemDict and when printing
NSLog(#"itemDictValues:%#",itemDict);
The output is in this format:
itemDictValues:
GTLPlusPerson 0xab821e0:
{etag:""LTv_6IJISeUQGTVXLjMeOtebkoM/eup2crXcelmpMFKesXWlGkJjCiE"" kind:"plus#person" id:"1145282979128841" objectType:"person" displayName:"FirstName LastName" image:{url} url:"https://plus.google.com/1145282979128841"}
From this I need to extract the values corresponding to id, displayName and url to my NSString variables, in this format
profileId=1145282979128841;
Name=FirstName LastName;
Profilepic=https://plus.google.com/1145282979128841;
How do I go about this?
try this ...
_profileId=(NSString*)((GTLPlusPerson*)itemDict).identifier;
_profileName= (NSString*)((GTLPlusPerson*)itemDict).displayName;
_profileImageURLPath=(NSString*)((GTLPlusPerson*)itemDict).image.url;
You just parse the Dictionary to get your desired information.
NSString *profileId = [itemDict objectForKey:#"id"];
NSString *displayName = [itemDict objectForKey:#"displayName"];
Now that image, I think that's in a dictionary itself. And since you haven't specified what's inside that dictionary, so here's what I think you should do:
NSDictionary *imageDict = [itemDict objectForKey:#"image"];
NSURL *imageURL = [imageDict objectForKey:#"url"];
Then getting the UIImage becomes pretty straightforward :
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:imageURL];
NSData *imageData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
UIImage *image = [[UIImage alloc] initWithData:imageData];
You should choose the sendAsynchronousRequest method as it happens in the background and doesn't hold up the functionality of your app.
For an NSDictionary
NSString *profileId = itemDict[#"id"]
NSString *name = itemDict[#"displayName"]
NSString *profilePic = itemDict[#"image"][#"url"]
If it is GTLPlusPerson object then access the properties with objective-c dot syntax
NSString *profileId = itemDict.id;
NSString *name = itemDict.displayName;
NSString *profilePic = itemDict.url;
Judging by your log, it appears it is a GTLPlusPerson object and not an NSDictionary
NSArray* peopleList = peopleFeed.items;
NSLog(#"peopleList %# ",peopleList.description);
for (NSArray *dict in peopleFeed.items) {
NSString *peopleStrID=(NSString*)((GTLPlusPerson*)dict).identifier;
NSLog(#"peopleStrID %#",peopleStrID);
NSString *peopleName = (NSString*)((GTLPlusPerson*)dict).displayName;
NSString *peoplePic = (NSString*)((GTLPlusPerson*)dict).image.url;
}
The easiest way is to use the code Google provides:
if ([[GPPSignIn sharedInstance] authentication]) {
// The user is signed in.
GTLQueryPlus *query = [GTLQueryPlus queryForPeopleGetWithUserId:#"me"];
GTLServicePlus* plusService = [[GTLServicePlus alloc] init];
plusService.retryEnabled = YES;
//auth = GTMOAuth2Authentication object from login
[plusService setAuthorizer:auth];
[plusService executeQuery:query
completionHandler:^(GTLServiceTicket *ticket,
GTLPlusPerson *person,
NSError *error) {
if (error) {
GTMLoggerError(#"Error: %#", error);
} else {
// Retrieve the display name and "about me" text
NSString *description = [NSString stringWithFormat:#"%#\n%#", person.displayName, person.aboutMe];
NSString *imageURL = person.image.url;
}
}];
} else {
//user is logged out
}
}