FBSDKLoginManager keep Facebook login since get user info - objective-c

I get user name and email using this (see below).
the problem, are that the login webview close, the call to initWithGraphPath:#"me" was done async, so user can see empty field by the time I get response to this call.
Is there a way to keep the facebook login webview open since the call to initWithGraphPath was completed?
Thanks!
-(void)loginButtonClicked_Facebook{
FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
[login
logInWithReadPermissions: #[#"public_profile", #"email"]
fromViewController:self
handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
if (error) {
NSLog(#"Process error");
} else if (result.isCancelled) {
NSLog(#"Cancelled");
} else {
if ([result.grantedPermissions containsObject:#"email"]){
NSLog(#"result is:%#",result);
[self fetchUserInfo];
}
}
}];
}
-(void)fetchUserInfo{
if ([FBSDKAccessToken currentAccessToken]){
NSLog(#"Token is available : %#",[[FBSDKAccessToken currentAccessToken]tokenString]);
[[[FBSDKGraphRequest alloc] initWithGraphPath:#"me" parameters:#{#"fields": #"id, name, email"}]
startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
if (!error){
NSString *userName = [result valueForKey:#"name"];
NSString *email = [result valueForKey:#"email"];
self.tfName.text=userName;
self.tfEmail.text=email;
self.tfEmailConfirmation.text=email;
NSLog(#"resultis:%#",result);
}else{
NSLog(#"Error %#",error);
}
}];
}
}

//YOURCONTROLLER.M
#import <FBSDKCoreKit/FBSDKCoreKit.h>
#import <FBSDKLoginKit/FBSDKLoginKit.h>
NSString *getFbid;
NSString *getFbFirstName,*getFBlastName, *getFbemail,*getfbBirthday,*getfbGender,*getFBpHone,*getFBlocation,*getFBcountry;
- (void) loginButton: (FBSDKLoginButton *)loginButton
didCompleteWithResult: (FBSDKLoginManagerLoginResult *)result
error: (NSError *)error{
NSLog(#"facebook login button test");
}
- (void) loginButtonDidLogOut:(FBSDKLoginButton *)loginButton{
NSLog(#"facebook logout button test");
}
-(void)loginButtonClicked
{
NSUserDefaults *defFacebookData = [NSUserDefaults standardUserDefaults];
FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
[login
logInWithReadPermissions: #[#"public_profile", #"user_friends", #"email"]
fromViewController:self
handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
if (error) {
DLog(#"Process error======%#",error.description);
indicators.hidden=YES;
[indicators stopAnimating];
} else if (result.isCancelled) {
DLog(#"Cancelled");
indicators.hidden=YES;
[indicators stopAnimating];
} else {
if ([FBSDKAccessToken currentAccessToken]) {
[[[FBSDKGraphRequest alloc] initWithGraphPath:#"me" parameters:#{#"fields": #"id, name, link, first_name, last_name, picture.type(large), email, birthday, bio ,location ,friends ,hometown , gender ,friendlists"}]
startWithCompletionHandler:^(
FBSDKGraphRequestConnection *connection, id result, NSError *error) {
if (!error)
{
// NSLog(#"fetched user:%#", result);
// [self fetchingFacebookFriends];
[defFacebookData setObject:[result objectForKey:#"email"] forKey:#"fbEmail"];
[defFacebookData setObject:[result objectForKey:#"id"] forKey:#"fbID"];
//PASS ID
getFbid = [result objectForKey:#"id"];
NSLog(#"getFbid========>%#",getFbid);
//PASS FIRST NAME
getFbFirstName=[result objectForKey:#"first_name"];
NSLog(#"first======>%#",getFbFirstName);
//PASS LAST NAME
getFBlastName=[result objectForKey:#"last_name"];
NSLog(#"first======>%#",getFBlastName);
//PASS EMAIL
getFbemail=[result objectForKey:#"email"];
NSLog(#"first======>%#",getFbemail);
//PASS PHONE
getfbGender=[result objectForKey:#"gender"];
NSLog(#"first======>%#",getfbGender);
[defFacebookData setObject:[result objectForKey:#"name"] forKey:#"fbName"];
// Image
FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc]
initWithGraphPath:[NSString stringWithFormat:#"me/picture?type=large&redirect=false"]
parameters:nil
HTTPMethod:#"GET"];
[request startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection,
id fbImageResult,
NSError *error) {
NSString *strURL = [NSString stringWithFormat:#"%#",[[fbImageResult objectForKey:#"data"] objectForKey:#"url"]];
NSLog(#"strURL=====>%#",strURL);
[defFacebookData setObject:strURL forKey:#"fbImage"];
[defFacebookData synchronize];
NSDictionary *fbdict=[NSDictionary dictionaryWithObjectsAndKeys:getFbid,#"id",getFbFirstName,#"first_name",getFBlastName,#"last_name",getFbemail,#"email",getfbGender,#"gender",strURL,#"fbImage", nil];
NSLog(#"done=========>%#",fbdict);
UIStoryboard*storyboard=[AppDelegate storyBoardType];
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
BOOL fblogin =[defaults boolForKey:#"KeyEditProfile"];
if (fblogin)
{
UIStoryboard*Storyboard=[AppDelegate storyBoardType];
DashboardVC* tabbarController = (DashboardVC*)[Storyboard instantiateViewControllerWithIdentifier:#"DashboardVCId"];
// tabbarController.dictFacebookdict =fbdict;
// tabbarController.strFBlogin =#"fbAllDataValue";
indicators.hidden=YES;
[indicators stopAnimating];
[self.navigationController pushViewController:tabbarController animated:YES];
}
else
{
EditFBVC *cpvc=(EditFBVC*)[storyboard instantiateViewControllerWithIdentifier:#"EditFBVCId"];
NSLog(#"get fb id ===%#",getFbid);
// cpvc.checkBtnclick =#"1";
cpvc.dictFacebookdict =fbdict;
cpvc.strFBlogin =#"fbAllDataValue";
indicators.hidden=YES;
[indicators stopAnimating];
[self.navigationController pushViewController:cpvc animated:YES];
} // [self facebookdataOnServer];
}];
}
else{
//[SVProgressHUD dismiss];
DLog(#"error is %#", error.description);
}
}];
}
}
}];
}

Related

The operation couldn't be completed (nsurlErrorDomain error -1012)

I have checked and applied it's all possible answers but not getting any success because I couldn't find the reason.
I am calling an API and sometimes it is working fine but some time it is giving me "The operation couldn't be completed (nsurlErrorDomain error -1012)" error.
My API calling code:
I have created this global method to call APIs. For this, I have created a singleton class.
-(void)getDispatchDetail:(NSString *)strDispatchId successBlock:(void(^)(NSDictionary *response))successBlock withFailureBlock:(FailureBlock)failureBlock{
NSString *urlString = [NSString stringWithFormat:#"%#%#",BASE_URL,END__POINT_getDispatchDetail];
[self MethodType:POST URL:urlString parameters:#{#"DispatchId":strDispatchId?strDispatchId:#""} withCookies:nil completionBlockWithSuccess:^(id responseObject, NSURLResponse *urlResponse) {
successBlock(responseObject);
} failure:^(NSError *error) {
[ProgressHUD dismiss];
failureBlock(error);
}];
}
-(void)MethodType:(METHOD_TYPE)methodType
URL:(NSString *)urlString
parameters:(NSDictionary *)param
withCookies:(BOOL)isCookies completionBlockWithSuccess:(void (^)(id responseObject, NSURLResponse *urlResponse))success
failure:(void (^)(NSError *error))failureRequest
{
if (isCookies){
//[ProgressHUD show:kSTRING_LOADING Interaction:NO];
}
/**
Create URl based on the Request Type
**/
NSURL *url;
switch (methodType) {
case GET:
if (param) {
NSString *strDict = [self stringFromDictionary:param];
NSString *strURL = [NSString stringWithFormat:#"%#?%#",urlString,strDict];
strURL = [strURL stringByReplacingOccurrencesOfString:#" " withString:#"%20"];
url = [NSURL URLWithString:strURL];
break;
}
url = [NSURL URLWithString:urlString];
break;
case PUT:
case POST:
case DELETE:
url = [NSURL URLWithString:urlString];
break;
default:
break;
}
/**
Create Reuqest based on the Request Type
**/
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
switch (methodType) {
case GET:
[req setHTTPMethod:#"GET"];
break;
case POST:
{
[req setHTTPMethod:#"POST"];
NSError *error = nil;
NSData *postData = [NSJSONSerialization dataWithJSONObject:param options:NSJSONWritingPrettyPrinted error:&error];
if (error) {
failureRequest(error);
}
[req setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[req setHTTPBody:postData];
}
break;
case PUT:
{
[req setHTTPMethod:#"PUT"];
NSError *error = nil;
if (param != nil) {
NSData *postData = [NSJSONSerialization dataWithJSONObject:param options:NSJSONWritingPrettyPrinted error:&error];
[req setHTTPBody:postData];
}
if (error) {
failureRequest(error);
}
[req setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
}
break;
case DELETE:
{
[req setHTTPMethod:#"DELETE"];
}
break;
default:
break;
}
//self.strAccessToken = #"Token ab6520a0805b11e82c750034548b74d02464e900";
//self.strAccessToken = [ETDataModelClass getUserAccessToken];
if ([[NSUserDefaults standardUserDefaults] valueForKey:API_PARAM_USER_ACCESS_TOKEN] != nil) {
NSDictionary *dict = [[NSUserDefaults standardUserDefaults] objectForKey:kUserLoginTokenAndData];
NSString *tokenType = [dict objectForKey:#"token_type"];
self.strAccessToken = [NSString stringWithFormat:#"%# %#",tokenType,[[NSUserDefaults standardUserDefaults] valueForKey:API_PARAM_USER_ACCESS_TOKEN]];
// [self.strAccessToken stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[req setValue:self.strAccessToken forHTTPHeaderField:API_ACCESS_TOKEN];
}
NSLog(#"ReqType : %# URL : %#, Param : %#", [self getMethodTypeName:methodType], url, param);
NSLog(#"User Token : %#",_strAccessToken);
[req setTimeoutInterval:60.0];
[NSURLConnection sendAsynchronousRequest:req
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *responseHeader, NSData *responseBody, NSError *error)
{
NSError *errorData = nil;
NSLog(#"Response Header : %#", responseHeader);
NSLog(#"Response : %#", [[NSString alloc] initWithData:responseBody encoding:NSUTF8StringEncoding]);
id responseObject1;
if(![responseBody isKindOfClass:[NSNull class]] && responseBody != nil)
responseObject1 = [NSJSONSerialization JSONObjectWithData:responseBody options:NSJSONReadingMutableLeaves error:&errorData];
else{
[ProgressHUD dismiss];
[Utility showAlertMessage:#"No Internet Connection. Make sure your device is connected to the internet." WithTitle:#""];
return ; // When response body nil we will return the control
}
// NSLog(#"Server Response ===> :\n %#", responseObject1);
// NSLog(#"Server Error ===> :\n %#", errorData);
if (error) {
if([responseObject1 isKindOfClass:[NSDictionary class]]){
if([[responseObject1 objectForKey:API_Alert_MESSAGE] isEqualToString:kAutologoutResponseFromServer]){
NSLog(#" Response ===== %# =====", responseObject1);
[[NSNotificationCenter defaultCenter] postNotificationName:kNotificationAutoLogout object:nil userInfo:responseObject1];
}
}
[ProgressHUD dismiss];
failureRequest(error);
return ;
}
else {
//[ProgressHUD dismiss];
if (!errorData) {
if (responseObject1 == nil) {
return [Utility showAlertMessage:NO_DATA_AVAILABLE WithTitle:#""];
}
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) responseHeader;
long statusCode = httpResponse.statusCode;
NSLog(#"statusCode : %ld",statusCode);
switch (statusCode) {
case API_STATUS_CODE_200: case API_STATUS_CODE_402:
if (success) {
success(responseObject1,responseHeader);
}
break;
case API_STATUS_CODE_500: case API_STATUS_CODE_400:
NSLog(#"responseHeader : %#",responseHeader);
NSLog(#"responseBody : %#",[[NSString alloc] initWithData:responseBody encoding:NSUTF8StringEncoding]);
NSLog(#"error : %#",error.localizedDescription);
NSLog(#"%#",[[NSString alloc] initWithData:responseBody encoding:NSUTF8StringEncoding]);
[Utility showAlertMessage:SERVER_ERROR WithTitle:#""];
[ProgressHUD dismiss];
break;
case API_STATUS_CODE_403:{
NSLog(#"auto logout warning : %#",responseBody);
[[NSNotificationCenter defaultCenter] postNotificationName:kNotificationAutoLogout object:nil userInfo:responseObject1];
[ProgressHUD dismiss];
break;
}
default:
NSLog(#"responseHeader : %#",responseHeader);
NSLog(#"responseBody : %#",[[NSString alloc] initWithData:responseBody encoding:NSUTF8StringEncoding]);
NSLog(#"error : %#",error.localizedDescription);
NSLog(#"%#",[[NSString alloc] initWithData:responseBody encoding:NSUTF8StringEncoding]);
if([responseObject1 isKindOfClass:[NSDictionary class]])
if([responseObject1 valueForKey:API_Alert_MESSAGE] && [responseObject1 valueForKey:API_Alert_MESSAGE] != nil)
[Utility showAlertMessage:[responseObject1 valueForKey:API_Alert_MESSAGE] WithTitle:#""];
[ProgressHUD dismiss];
break;
}
}
else{
failureRequest(errorData);
}
}
}];
}

How to parse ShopStyle JSON in Objective-C

I have a snippet of some JSON which contains ShopStyle products here: https://docs.google.com/document/d/1konfjof33sgNngxIgq_sCyKmCcDda-ziXnOfUUxeKas/edit?usp=sharing
How do I go about getting the products' names and ids from the JSON? So far, I have the following code:
NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:#"http://api.shopstyle.com/api/v2/products?pid=%#&fts=%#&offset=0&limit=50", apiKey, searchkeywords]];
NSLog(#"%#", URL);
[NSURLConnection sendAsynchronousRequest:[[NSURLRequest alloc] initWithURL:URL] queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (error) {
//[self.delegate fetchingGroupsFailedWithError:error];
} else {
//[self.delegate receivedGroupsJSON:data];
NSDictionary *rest_data = [NSJSONSerialization JSONObjectWithData:data
options:0
error:NULL];
NSLog(#"rest_data = %#", rest_data);
for (NSDictionary *topComment in[rest_data objectForKey:#"products"]) {
[self processCommentThread:topComment andLevel:0];
}
NSLog(#"GET COMMENTS RETURN:%#", commentsContainer);
[self performSelectorOnMainThread:#selector(doneFormatting) withObject:nil waitUntilDone:YES];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:[NSString stringWithFormat:#"%#", rest_data] delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:nil, nil];
[alert show];
}
}];
/*
PSSProductQuery *productQuery = [[PSSProductQuery alloc] init];
productQuery.searchTerm = searchBar.text;
__weak typeof(self) weakSelf = self;
[[PSSClient sharedClient] searchProductsWithQuery:productQuery offset:nil limit:nil success:^(NSUInteger totalCount, NSArray *availableHistogramTypes, NSArray *products) {
weakSelf.products = products;
[resultsTableView reloadData];
NSLog(#"_products = %#", _products);
resultsTableView.hidden = NO;
} failure:^(int *operation, NSError *error) {
}];
*/
}
- (void)processCommentThread:(NSDictionary *)comments andLevel:(int)level {
#autoreleasepool {
NSMutableDictionary *comment = [[NSMutableDictionary alloc] init];
if (!([comments objectForKey:#"name"] == nil)) {
[comment setObject:[comments objectForKey:#"name"] forKey:#"name"];
}
if (!([comments objectForKey:#"id"] == nil)) {
[comment setObject:[comments objectForKey:#"id"] forKey:#"id"];
}
}
}
-(void)doneFormatting{
[myTableView reloadData];
}

Can't load facebook profile image

I have a problem with uploading profile picture from facebook to my API and saving to Parse. This code is from Udemy. I'm using Xcode 7.2.
Error:
2016-01-18 10:14:15.296 MatchedUp[14381:5418567] Error in FB request Error Domain=com.facebook.sdk Code=5 "(null)" UserInfo={com.facebook.sdk:HTTPStatusCode=400, com.facebook.sdk:ErrorSessionKey=<PFReceptionist: 0x12663d2e0>, com.facebook.sdk:ParsedJSONResponseKey={
body = {
error = {
code = 100;
"fbtrace_id" = "FXTRrxOh0+c";
message = "(#100) Tried accessing nonexisting field (photo) on node type (User)";
type = OAuthException;
};
};
code = 400;
}}
Code:
-(void)updateUserInformation
{
//
FBRequest *request = [FBRequest requestForGraphPath:#"me/?fields=name,birthday,first_name,location,gender,interested_in,photo"];
[request startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
if(!error){
NSDictionary *userDictionary = (NSDictionary *)result;
//create URL
NSString *facebookID = userDictionary[#"id"];
NSLog(#"%#",result);
NSURL *pictureURL = [NSURL URLWithString:[NSString stringWithFormat:#"https://graph.facebook.com/%#/picture?type=large&return_ssl_resources=1", facebookID]];
NSData *imageData = [NSData dataWithContentsOfURL:pictureURL];
// UIImage *fbImage = [UIImage imageWithData:imageData];
NSLog(#"%#",result);
NSMutableDictionary *userProfile = [[NSMutableDictionary alloc] initWithCapacity:8];
NSLog(#"%#",result);
if(userDictionary[#"name"]){
userProfile[kCCUserProfileNameKey] = userDictionary[#"name"];
}
if(userDictionary[#"user_birthday"]){
userProfile[kCCUserProfileBirthdayKey] = userDictionary[#"user_birthday"];
}
if(userDictionary[#"first_name"]){
userProfile[kCCUserProfileFirstNameKey] = userDictionary[#"first_name"];
}
if(userDictionary[#"location"][#"name"]){
userProfile[kCCUserProfileLocationNameKey] = userDictionary[#"location"][#"name"];
}
if(userDictionary[#"gender"]){
userProfile[kCCUserProfileGenderKey] = userDictionary[#"gender"];
}
if(userDictionary[#"interested_in"]){
userProfile[kCCUserProfileInterestedInKey] = userDictionary[#"interested_in"];
}
if([pictureURL absoluteString]){
userProfile[kCCUserProfilePictureURL] = [pictureURL absoluteString];
}
[[PFUser currentUser] setObject: userProfile forKey:kCCUserProfileKey];
[[PFUser currentUser] saveInBackground];
[self requestImage];
}
else{
NSLog(#"Error in FB request %#", error);
}
}];
}
-(void) uploadPFFileToParse:(UIImage *)image
{
NSData *imageData = UIImageJPEGRepresentation(image, 0.8);
if(!imageData){
NSLog(#"imageData was not found");
return;
}
PFFile *photoFile = [PFFile fileWithData:imageData];
[photoFile saveInBackgroundWithBlock:^(BOOL succeeded, NSError * _Nullable error) {
if(succeeded){
PFObject *photo = [PFObject objectWithClassName:kCCPhotoClassKey];
[photo setObject:[PFUser currentUser] forKey:kCCPhotoUserKey];
[photo setObject:photoFile forKey:kCCPhotoPictureKey];
[photo saveInBackgroundWithBlock:^(BOOL succeeded, NSError * _Nullable error) {
NSLog(#"Photo saved successfully");
}];
}
}];
}
-(void) requestImage
{
PFQuery *query = [PFQuery queryWithClassName:kCCPhotoClassKey];
[query whereKey:kCCPhotoUserKey equalTo:[PFUser currentUser]];
[query countObjectsInBackgroundWithBlock:^(int number, NSError * _Nullable error) {
if(number == 0 )
{
PFUser *user = [PFUser currentUser];
self.imageData = [[NSMutableData alloc] init];
NSURL *profilePictureUrl = [NSURL URLWithString:user [kCCUserProfileKey][kCCUserProfilePictureURL]];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:profilePictureUrl cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:4.0f];
NSURLConnection *urlConnection = [[NSURLConnection alloc]initWithRequest:urlRequest delegate:self];
if(!urlConnection){
NSLog(#"Failed to Download Picture");
}
}
}];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[self.imageData appendData:data];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
UIImage *profileImage = [UIImage imageWithData:self.imageData];
[self uploadPFFileToParse:profileImage];
}
#end
Any idea how can i fix this problem?
Thanks a lot!
Try this.
- (void)getFBProfilePicture {
NSString *facebookId = #"yourFacebookId";
NSString *imageUrl = [NSString stringWithFormat:#"https://graph.facebook.com/%#/picture?type=large&return_ssl_resources=1", facebookId];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageUrl]];
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = [UIImage imageWithData:imageData];
});
});
}

facebook sharing from iPhone app

In my iphone app i am accessing my facebook info and sending it to the server. From server facebook sharing should happen
I have created my app in FB and while clicking sync button i am able to go to the FB login page.After loged in it asks for the authentication
But it just asking for "basic info" not for public sharing etc (i have included that in my FB app)
-(IBAction)fbConnect:(id)sender{
flag = 1;
AppDelegate *appDelegate = [[UIApplication sharedApplication]delegate];
if (appDelegate.session.isOpen) {
[self updateView];
} else {
if (appDelegate.session.state != FBSessionStateCreated) {
appDelegate.session = [[FBSession alloc] init];
}
[appDelegate.session openWithCompletionHandler:^(FBSession *session,
FBSessionState status,
NSError *error) {
[self updateView];
}];
}
NSLog(#"string issss %#",string);
}
- (void)updateView {
AppDelegate *appDelegate = [[UIApplication sharedApplication]delegate];
if (appDelegate.session.isOpen) {
string = [NSString stringWithFormat:#"%#",
appDelegate.session.accessToken];
NSLog(#"string issss %#",string);
NSString *urlstrng;
if(flag == 1){
urlstrng = [NSString stringWithFormat:#"https://graph.facebook.com/me?access_token=%#",string];
[self dataFetching:urlstrng];
}
if(flag == 2){
urlstrng = [NSString stringWithFormat:#"https://graph.facebook.com/me/friends? access_token=%#",string];
[self dataFetching:urlstrng];
}
} else {
string = [NSString stringWithFormat:#"%#",
appDelegate.session.accessToken];
NSString *urlstrng;
if(flag == 1){
urlstrng = [NSString stringWithFormat:#"https://graph.facebook.com/me?access_token=%#",string];
[self dataFetching:urlstrng];
}
if(flag == 2){
urlstrng = [NSString stringWithFormat:#"https://graph.facebook.com/me/friends?access_token=%#",string];
[self dataFetching:urlstrng];
}
}
}
-(void)dataFetching:(NSString*)strng1{
NSURL *url = [NSURL URLWithString:strng1];
ProfileConnector *obj = [[ProfileConnector alloc] init];
obj.delegate1 = self;
[obj parsingJson:url];
}
I believe you are not requesting extra items through your code. You can do it by using openSessionWithAllowLoginUI.
- (BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI {
NSArray *permissions = [[NSArray alloc] initWithObjects:
#"user_location",
#"user_birthday",
#"user_likes",
#"email",
nil];
return [FBSession openActiveSessionWithPermissions:permissions
allowLoginUI:allowLoginUI
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error) {
[self sessionStateChanged:session
state:state
error:error];
}];
}

how to return result after OpenWithCompletionHandler: is complete

Want to query a photo in the Coredata database
this is my code
this is the NSObjectSubclass category
//Photo+creak.h
#import "Photo+creat.h"
#implementation Photo (creat)
+(Photo *)creatPhotoByString:(NSString *)photoName inManagedObjectContext:(NSManagedObjectContext *)context{
Photo *picture = nil;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Photo"];
request.predicate = [NSPredicate predicateWithFormat:#"name = %#", photoName];
NSArray *matches = [context executeFetchRequest:request error:nil];
if (!matches || [matches count]>1) {
//error
} else if ([matches count] == 0) {
picture = [NSEntityDescription insertNewObjectForEntityForName:#"Photo" inManagedObjectContext:context];
picture.name = photoName;
} else {
picture = [matches lastObject];
}
return picture;
}
+ (BOOL)isPhoto:(NSString *)photoName here:(NSManagedObjectContext *)context{
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Photo"];
request.predicate = [NSPredicate predicateWithFormat:#"name = %#", photoName];
NSArray *matches = [context executeFetchRequest:request error:nil];
switch ([matches count]) {
case 1:
return YES;
break;
default:
return NO;
break;
}
}
#end
code inside of view controller
//View Controller
- (IBAction)insertData:(UIButton *)sender {
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
url = [url URLByAppendingPathComponent:#"test"];
UIManagedDocument *defaultDocument = [[UIManagedDocument alloc] initWithFileURL:url];
if (![[NSFileManager defaultManager] fileExistsAtPath:[url path]]) {
[defaultDocument saveToURL:defaultDocument.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:NULL];
}
[defaultDocument openWithCompletionHandler:^(BOOL success) {
[Photo creatPhotoByString:#"test" inManagedObjectContext:defaultDocument.managedObjectContext];
[defaultDocument saveToURL:defaultDocument.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:NULL];
}];
[sender setTitle:#"Okay" forState:UIControlStateNormal];
[sender setEnabled:NO];
}
- (IBAction)queryFromDatabase:(UIButton *)sender {
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
url = [url URLByAppendingPathComponent:#"test"];
UIManagedDocument *defaultDocument = [[UIManagedDocument alloc] initWithFileURL:url];
BOOL isItWorking = [checkPhoto isPhoto:#"test" inManagedDocument:defaultDocument];
if (isItWorking) {
[sender setTitle:#"Okay" forState:UIControlStateNormal];
} else {
[sender setTitle:#"NO" forState:UIControlStateNormal];
}
}
The NSObject Class that hook them up.
// checkPhoto.m
#import "checkPhoto.h"
#implementation checkPhoto
+ (BOOL)isPhoto:(NSString *)photoToCheck inManagedDocument:(UIManagedDocument *)document{
__block BOOL isPhotoHere = NO;
if (document.documentState == UIDocumentStateClosed) {
[document openWithCompletionHandler:^(BOOL success) {
isPhotoHere = [Photo isPhoto:photoToCheck here:document.managedObjectContext];
}];
}
return isPhotoHere;
}
#end
The coredata only have on Entity named "Photo", and it got only one attribute "name".
The problem is that the return always get execute before the block is complete and always return NO.
Test code here
Or should I do something else than openWithCompletionHandler when querying?
You need to rework your method to work asynchronously, like -openWithCompletionHandler:. It needs to take a block which is invoked when the answer is known and which receives the answer, true or false, as a parameter.
Then, the caller should pass in a block that does whatever is supposed to happen after the answer is known.
Or, alternatively, you should delay the whole chunk of logic which cares about the photo being in the database. It should be done after the open has completed.
You'd have to show more code for a more specific suggestion.
So, you could rework the isPhoto... method to something like:
+ (BOOL)checkIfPhoto:(NSString *)photoToCheck isInManagedDocument:(UIManagedDocument *)document handler:(void (^)(BOOL isHere))handler {
if (document.documentState == UIDocumentStateClosed) {
[document openWithCompletionHandler:^(BOOL success) {
handler([Photo isPhoto:photoToCheck here:document.managedObjectContext]);
}];
}
else
handler(NO);
}
Then you can rework this:
- (IBAction)queryFromDatabase:(UIButton *)sender {
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
url = [url URLByAppendingPathComponent:#"test"];
UIManagedDocument *defaultDocument = [[UIManagedDocument alloc] initWithFileURL:url];
[checkPhoto checkIfPhoto:#"test" isInManagedDocument:defaultDocument handler:^(BOOL isHere){
if (isHere) {
[sender setTitle:#"Okay" forState:UIControlStateNormal];
} else {
[sender setTitle:#"NO" forState:UIControlStateNormal];
}
}];
}
Try that
+(BOOL)isPhoto:(Photo *)photo inDataBase:(UIManagedDocument *)defaultDocument{
__block BOOL isPhotoThere = NO;
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[defaultDocument openWithCompletionHandler:^(BOOL success) {
[defaultDocument.managedObjectContext performBlock:^{
isPhotoThere = [Photo checkPhoto:photo];
dispatch_semaphore_signal(sema);
}];
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
dispatch_release(sema);
return isPhotoThere;
}