Parse.com - Another user is already linked to this facebook id - parse-platform

I'm using parse.com's api and trying to link a currently active user to his to facebook account.
I keep bumbing into:
Another user is already linked to this facebook id
As to my question: How do I get the user's connected facebook id? I'd like to switch my current anonymous user with the active and logged in user.
Thank you

I solved this by logging out the current user then logging in. Works well.
[PFFacebookUtils linkUser:[PFUser currentUser] permissions:permissionsArray block:^(BOOL success, NSError *error) {
if (!success) {
if (!error) {
NSLog(#"User Cancelled");
} else {
if(error.code == 208) {
[PFUser logOut];
[PFFacebookUtils logInWithPermissions:permissionsArray block:^(PFUser *user, NSError *error) {
if(error) {
NSLog(#"An error occurred: %#", error);
} else {
// Carry on
}
}];
} else {
NSLog(#"An error occurred: %#", error);
}
}
} else {
// Carry on
}
}];

You can ignore it as it's a warning to notify you that the Facebook account was already linked(In your case it's to the anonymous user), not an error.
The last assigned user will be linked to the Facebook account. So your original intention - " To link the currently active user to his to facebook account" works even though a warning will be raised to notify you that the anonymous user was linked to the same facebook account.
To avoid this warning, always logout the anonymous user before linking Facebook user with the currently active user.

I faced same issue and solution was even better, just ignore this error. It is kind of warning. It is thrown but user gets linked to another account.

Check if you are asking for permissions when you try to link like this:
[PFFacebookUtils linkUser:[PFUser currentUser] permissions:[NSArray arrayWithObjects:#"publish_stream",#"publish_actions", #"user_about_me", #"user_photos", #"read_stream",#"friends_photos",#"email",#"user_birthday",#"user_location", nil] block:^(BOOL succeeded, NSError *error) {
if (succeeded) {
[self login:nil];
NSLog(#"Woohoo, user logged in with Facebook!");
}else{
NSLog(#"%#", [[error userInfo] objectForKey:#"error"]);
NSLog(#"An error occurred: %#", error);
}
}];
In my case i was passing nil param for permissions. May be it will be helpfull for someone else

Related

Cloudkit: " error saving record WRITE operation not permitted"

I'm trying to save a record CloudKit but I'm getting the following error from cloudkit:
error saving record este es error: Error saving record <CKRecordID: 0x7fef15b5d2a0; 2:(_defaultZone:__defaultOwner__)> to server: WRITE operation not permitted
Here is how I'm trying to save the record:
[publicDatabase saveRecord:recordContent completionHandler:^(CKRecord *record, NSError *error){
if (!error)
{
NSLog(#"saved!!!");
}
else
{
if ([[error.userInfo valueForKey:#"ErrorDescription"] isEqualToString:#"record to insert already exists"])
{
NSLog(#"record already exist %#",[error.userInfo valueForKey:#"ErrorDescription"]);
}
NSLog(#"error saving record : %#",error.localizedDescription);
}
}];
But before had I check if cloudkit is available:
[myContainer accountStatusWithCompletionHandler:^(CKAccountStatus accountStatus, NSError *error)
{
NSLog(#" no error but status %ld",accountStatus);
if (((accountStatus == 3) || (accountStatus == 2)) && (!error))
{
NSLog(#" no error but status %ld",accountStatus);
// typedef NS_ENUM(NSInteger, CKAccountStatus) {
// /* An error occurred when getting the account status, consult the corresponding NSError */
// CKAccountStatusCouldNotDetermine = 0,
// /* The iCloud account credentials are available for this application */
// CKAccountStatusAvailable = 1,
// /* Parental Controls / Device Management has denied access to iCloud account credentials */
// CKAccountStatusRestricted = 2,
// /* No iCloud account is logged in on this device */
// CKAccountStatusNoAccount = 3,
//
// }
}
if (error)
{
NSLog(#" accountStatus error %#",error);
}
} ];
Where I'm getting status 1, meaning CKAccountStatusAvailable.
Any of you knows why this is happening it has been working fine until the last record or any of you knows a work around this?
I'll really appreciate your help.
You need to set permission to allow a user to write (or delete) a record created by someone else. You do that in the Development Environment, under Schema, Record Types, select the specific record, then over on the right there is a drop down menu labelled Security. Grant to the Role ' Authenticated' the right to Read and Write. Then deploy to Production.
This was moved in the latest CloudKit, took me a while to track it down.
Beware, this isn't instant, it takes a while for these changes to propagate after saving them. Come back later and refresh the page to see if they've been applied.
If you are still getting this error after setting these permissions and letting them propagate then it's likely that your iCloud Login in Simulator is messed up. Logging out of iCloud and logging in again fixed this for me.
I spent 2 days for "Permission failure (10/2007)". All permissions and security roles was set as in William.T picture. Relogin into iCloud doesn't got any results.
The snag was in one small setting (not documented by Apple) - it was switcher "iCloud Drive" which located in
Settings/[your account]/iCloud/iCloud Drive
on my device. Apple's documentation is terrible! no one will return me 2 days spent.
Hope this helps someone with the same problem.
In my case i forgot to do a basic check: make sure you're logged in with your Apple ID and make sure the iCloud checkmark for your application is turned on.
This can happen especially using Simulators.

Inconsistent results creating bidirectional relationship between PFUser and PFObjects

I am attempting to create a bidirectional relationship between a PFUser and some PFObjects using PFRelations.
First I create a Posting and save that in the background.
And in the completion block I add the new posting in the PFUser by appending to the list of Postings that are already related to this User and re-save the User with a synchronous save call.
The Posting is always saved correctly with the correct Relation to the User, however, the Relation back to the Posting in the User only works intermittently. Stepping through the code results in the correct outcome each time which leads me to believe it's some sort of race condition. What would cause this behavior? Is there a better way to achieve the desired relationships?
PFUser *currentUser = [PFUser currentUser];
PFObject *posting = [PFObject objectWithClassName:#"Postings"];
__weak HLReviewPostItemViewController *myself = self;
posting[#"title"] = self.createdItem[#"title"];
posting[#"price"] = self.createdItem[#"price"];
posting[#"owner"] = currentUser;
[posting saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (!error) {
PFGeoPoint *currentGeoPoint = [myself.locationManager getCurrentGeoPoint];
[currentUser setObject:currentGeoPoint forKey:#"geoPoint"];
PFRelation *postingsForUser = [currentUser relationForKey:#"postings"];
[postingsForUser addObject:posting];
NSError *error;
[currentUser save:&error];
if (!error) {
[myself.dataManager fetchLocalUsers];
} else {
NSLog(#"Error saving Posting in user relation: %#", error);
}
} else {
NSLog(#"Error saving Posting: %#", error);
}
}];
When you save the posting, because the posting has a column that stores the owner, the owner - the parent, also gets saved automatically - very nice feature of Parse.
When you step through the code automatic save is executed and finished before your next re-save. But when you run the code, there is no guarantee which save to PFUser object would occur first.

authData column isn't updated properly on Parse.com for Anonymous users

I'm creating anonymous users from an iOS application using this code:
[PFAnonymousUtils logInWithBlock:^(PFUser *user, NSError *error) {
if (error)
{
NSLog(#"Anonymous login failed.");
} else
{
user.isAnonymous = true;
NSLog(#"Anonymous user logged in.");
}
}];
From time to time the authData column isn't populated with the "Anonymous" text and this means when I try to test if the user is anonymous it incorrectly reports that the user isn't anonymous.
As far as I know the column should be populated automatically and I'm not really sure why this happens.
This is how it looks:(There are more even more intercalated)
Do you have any idea why this happens?
Thanks.

What is the correct way to handle stale NSURL bookmarks?

When resolving an NSURL from a security scoped bookmark, if the user has renamed or moved that file or folder, the bookmark will be stale. Apple's document says this regarding staleness:
isStale
On return, if YES, the bookmark data is stale. Your app should
create a new bookmark using the returned URL and use it in place of
any stored copies of the existing bookmark.
Unfortunately, this rarely works for me. It may work 5% of the time. Attempting to create a new bookmark using the returned URL results in an error, code 256, and looking in Console reveals a message from sandboxd saying deny file-read-data on the updated URL.
Note If regenerating the bookmark does work, it seems to only work the first time it is regenerated. It seems to never work should the folder/file be moved/renamed again.
How I initially create & store the bookmark
-(IBAction)bookmarkFolder:(id)sender {
_openPanel = [NSOpenPanel openPanel];
_openPanel.canChooseFiles = NO;
_openPanel.canChooseDirectories = YES;
_openPanel.canCreateDirectories = YES;
[_openPanel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) {
if (_openPanel.URL != nil) {
NSError *error;
NSData *bookmark = [_openPanel.URL bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope
includingResourceValuesForKeys:nil
relativeToURL:nil
error:&error];
if (error != nil) {
NSLog(#"Error bookmarking selected URL: %#", error);
return;
}
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:bookmark forKey:#"bookmark"];
}
}];
}
Code that resolves the bookmark
-(void)resolveStoredBookmark {
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSData *bookmark = [userDefaults objectForKey:#"bookmark"];
if (bookmark == nil) {
NSLog(#"No bookmark stored");
return;
}
BOOL isStale;
NSError *error;
NSURL *url = [NSURL URLByResolvingBookmarkData:bookmark
options:NSURLBookmarkResolutionWithSecurityScope
relativeToURL:nil
bookmarkDataIsStale:&isStale
error:&error];
if (error != nil) {
NSLog(#"Error resolving URL from bookmark: %#", error);
return;
} else if (isStale) {
if ([url startAccessingSecurityScopedResource]) {
NSLog(#"Attempting to renew bookmark for %#", url);
// NOTE: This is the bit that fails, a 256 error is
// returned due to a deny file-read-data from sandboxd
bookmark = [url bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope
includingResourceValuesForKeys:nil
relativeToURL:nil
error:&error];
[url stopAccessingSecurityScopedResource];
if (error != nil) {
NSLog(#"Failed to renew bookmark: %#", error);
return;
}
[userDefaults setObject:bookmark forKey:#"bookmark"];
NSLog(#"Bookmark renewed, yay.");
} else {
NSLog(#"Could not start using the bookmarked url");
}
} else {
NSLog(#"Bookmarked url resolved successfully!");
[url startAccessingSecurityScopedResource];
NSArray *contents = [NSFileManager.new contentsOfDirectoryAtPath:url.path error:&error];
[url stopAccessingSecurityScopedResource];
if (error != nil) {
NSLog(#"Error reading contents of bookmarked folder: %#", error);
return;
}
NSLog(#"Contents of bookmarked folder: %#", contents);
}
}
When the bookmark is stale, the resulting resolved URL does point to the correct location, I just can't actually access the file despite the fact that [url startAccessingSecurityScopedResource] returns YES.
Perhaps I'm misinterpreting the documentation regarding stale bookmarks, but I'm hoping I'm just doing something stupid. Popping an NSOpenPanel each time a bookmarked file/folder is renamed or moved, my only other option at this point, seems ridiculous.
I should add that I have com.apple.security.files.bookmarks.app-scope, com.apple.security.files.user-selected.read-write, and com.apple.security.app-sandbox all set to true in my entitlements file.
After a lot of disappointing testing I've come to the following conclusions. Though logical, they're disappointing since the resulting experience for users is far from ideal and a significant pain for developers depending on how far they're willing to go to help users re-establish references to bookmarked resources.
When I say "renew" below, I mean "generate a new bookmark to replace a stale bookmark using the URL resolved from the stale bookmark."
Renewal always works as long as the bookmarked resource is moved or renamed within a directory that your app already has permission to access. So, by default, it always works inside your application's container folder.
Renewal fails if a bookmarked resource is moved into a folder your application does not have permission to access. e.g. User drags a folder from your container folder to some folder outside the container folder. You will be able to resolve the URL, but not access nor renew the bookmark.
Renewal fails if a bookmarked resource lives in a folder your application doesn't have access to and is then renamed. This means a user can explicitly grant your application access to a resource, then inadvertently revoke that access just by renaming it.
Resolution fails if a resource is moved to another volume. Not sure if this is a limitation of bookmarks in general or just when used in a sandboxed application.
For issues 2 & 3 you're in a decent position as the developer since resolution of the bookmarked URL does work. You can at least lead the user by telling them exactly which resources they need to grant your app access to and where they are. The experience could be improved by having them select a folder that contains (directly or indirectly) all resources that you need to renew a bookmark for. This could even be the volume, which solves the problem completely if they're willing to give your application this much access.
For issue 4, resolution doesn't work at all. The user will have to relocate the file without any hints since you can't resolve the new location. One thing I've done in my current app that has reduced the pain of this issue is to add an extended attribute to any resource I store a bookmark for. Doing this at least lets me have the user choose a folder to search for previously associated resources.
Frustrating limitations, but bookmarks still win over storing static paths.

iOS 6 contacts access alert never showed on debug

My app on the appstore is accessing the iPhone contacts, after the users downloaded it on iOS 6 it can't access the iPhone contacts while its working fine on iOS 5
the problem is the new privacy settings apple has put in iOS 6 .. so after searching i found out that i have to do the following in my code to be able to access the user contacts:
//in order to test addressbook availability we have to attempt to create an addressbook instance using ABAddressBookCreateWithOptions
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 60000
// Request authorization to Address Book
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
ABAddressBookRequestAccessWithCompletion(addressBookRef,
^(bool granted, CFErrorRef error) {
if (granted)
[self loadContacts];
});
} else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
// The user has previously given access, add the contact
[self loadContact];
} else {
}
#endif //end iOS6+
//ABAddressBookCreateWithOptions not available or succeeded. return YES;
[self loadContacts];
My problem now is while debugging on the device, the alert is not showing, i don't know why ?
I know that the above code should work fine, but only when the app is submitted to the appstore but i want to test that in debug mode before submission ?
Any advice ?
Appreciate your support.
Thanks.
I have managed to get it resolved
Here is the new code after a slight modification:
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 60000
__block MyClassType *controller = self;
// Request authorization to Address Book
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
ABAddressBookRequestAccessWithCompletion(addressBookRef,
^(bool granted, CFErrorRef error) {
if (granted)
[controller loadContacts];
});
} else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
// The user has previously given access, add the contact
[self loadContacts];
} else {
}
#else
[self loadContacts];
#endif
The key to be able to test it is to Reset the Privacy and location settings from Settings>>General>>Reset>>Reset Location & Privacy
It worked fine with me.
Resetting Location & Privacy doesn't work for me.
My authorization status is always kABAuthorizationStatusAuthorized, regardless of whether I clear simulator settings and then reset Location and Privacy.

Resources