I'm using the anonymous user feature of Parse so that each user can create a "Favorite" list and not have to create an account on the app.
When a user is on an item detail page there will be a "Star" image and when selected that object should be added to their Favorite List, which will be a table on another UIViewController.
Here's my code when adding to favorites:
PFQuery * query = [PFQuery queryWithClassName:#"ClassA"];
[query whereKey:#"item_name" equalTo:self.itemLabel.text];
[query getFirstObjectInBackgroundWithBlock:^(PFObject *object, NSError *error) {
if (error)
{
NSLog(#"Error: %#", error);
}
else
{
PFUser * user = [PFUser currentUser];
self.favRelation = [user relationforKey:#"favorite"];
[self.favRelation addObject:object];
[user saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error)
{
NSLog(#"Error: %# %#", error, [error userInfo]);
}
else
{
NSLog(#"Yay!!");
}
}];
}
}];
When this code runs, the Relation was added to my User table in Parse, but when I select "View Relations", I just see the User again.
Am I over looking something or missing something?
Related
Is there a way to add a document to the Cloud Store but being able to set its documentid. The reason I'd like to do that is because I'd like to have the following structure:
users/{user}/userdata
And would like to use userId from the authenticated user in the place of the user's documentId. The examples always show an auto generated DocumentID for the created document. Can't find any documentation that lets me know how to explicitly set the DocumentId.
__block FIRDocumentReference *ref =
[[self.db collectionWithPath:#"users"] addDocumentWithData:#{
#"first": #"Ada",
#"last": #"Lovelace",
#"born": #1815
} completion:^(NSError * _Nullable error) {
if (error != nil) {
NSLog(#"Error adding document: %#", error);
} else {
NSLog(#"Document added with ID: %#", ref.documentID);
}
}];
Figured it out ... hopefully this will help someone else:
[[[self.db collectionWithPath:#"users"] documentWithPath:user.uid] setData:#{
#"name": #"Jane Smith",
#"State": #"CA",
#"country": #"USA"
} completion:^(NSError * _Nullable error) {
if (error != nil) {
NSLog(#"Error writing document: %#", error);
} else {
NSLog(#"Document successfully written!");
}
}];
Duplicate of :
https://stackoverflow.com/questions/17037149/ios-parse-com-app-crashes-while-retrieve-data-from-cache-nsinternalinconsiste
have implemented an iOS App using Parse.com
Trying to retrieve from cache.
While retrieve data from cache i got an error like this:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'This query has an outstanding network connection. You have to wait until it's done.'
When i browse for the issues i found that:
Some suggested that it may happens due to making two query calls on the same query object without waiting for the first to complete.
how to avoid these simultatanius calls in this app
query setLimit: limit];
[query setSkip: skip];
//RETRIEVING FROM CACHE
query.cachePolicy = kPFCachePolicyCacheThenNetwork;
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error)
{
[allObjects removeAllObjects]; //Added regarding cache ******
// The find succeeded. Add the returned objects to allObjects
[allObjects addObjectsFromArray:objects];
if (objects.count == limit) {
// There might be more objects in the table. Update the skip value and execute the query again.
skip += limit;
[query setSkip: skip];
// Go get more results
weakPointer();
}
else
{
// We are done so return the objects
block(allObjects, nil);
}
}
else
{
block(nil,error);
}
}];
To avoid simultaneous calls of a PFQuery, call [query cancel] before findObjects is called:
query.cachePolicy = kPFCachePolicyCacheThenNetwork;
[query cancel]; //cancels the current network request being made by this query (if any)
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
//do stuff
}];
Careful:
[query cancel];
Does not work if you're expecting the callback.
Solution:
#property (nonatomic) BOOL isCurrentlyFetching; // Makes sure Parse is called only
-(void)myQuery
{
if (_isCurrentlyFetching) { return; } // Bails if currently fetching
_isCurrentlyFetching = YES;
//RETRIEVING FROM CACHE
query.cachePolicy = kPFCachePolicyCacheThenNetwork; // Whatever your cache policy is
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error){
// Your code...
}
else{
// Your code...
}
_isCurrentlyFetching = NO;
}];
}
I am trying to check if user has already granted publish permission or not. if he has not granted permissions before then i navigate him to permissions screen via: requestNewPublishPermissions
-(void)checkPermissions
{
// Get the most recent status
[FBRequestConnection
startWithGraphPath:#"me/permissions"
completionHandler:^(FBRequestConnection *connection,
id result,
NSError *error) {
if (!error) {
//This Condition Never Executed
if([[result objectForKey:#"data"] objectForKey:#"publish_actions"])
{
//permissions exist
}
else
{
[self openSessionForPublishPermissions];
}
NSString *permission = [[result objectForKey:#"data"] objectForKey:#"publish_actions"];
NSLog(#"permissions data = %#",data);
}
else
{
NSLog(#"error"); //Control goes to this block
}
}];
}
In code above if(!error) block is never executed and it always returns Error
Where i'm going wrong? Am i missing something?
You can see permissions in the active session. Here is how it's done in the HelloFacebookSample :
if ([FBSession.activeSession.permissions indexOfObject:#"publish_actions"] == NSNotFound) {
// permission does not exist
} else {
// permission exists
}
Instead of manually checking the permissions, you could check if the session is active and request publish permissions: if the user has already granted the permissions, an additional confirmation dialog will not be posted. See the code sample below:
- (void)requestWritePermission:(UIViewController *)viewController channel:(NSString *)channel callback:(void(^)(BOOL success))callback
{
if ([FBSession.activeSession isOpen])
{
[FBSession.activeSession requestNewPublishPermissions:#[#"publish_actions"]
defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:^(FBSession *session, NSError *error) {
callback(error == nil);
}];
}
else
{
// Attempt to request publish permission without read permission.
}
}
The code is not complete, but should get you started.
Can anyone help me. I cannot figure out how to make a single FQL query using the latest Facebook SDK (v 3.1) for iOS to get birthday and email of user's friend. When I query for fields like name i get the correct value but get null for email and birthday field.
Here is my code
- (void)facebookViewControllerDoneWasPressed:(id)sender {
// we pick up the users from the selection, and create a string that we use to update the text view
// at the bottom of the display; note that self.selection is a property inherited from our base class
for (id<FBGraphUser> user in _friendPickerController.selection) {
_nameTxt.text = user.name;
NSString *fql = [NSString stringWithFormat:#"SELECT email, birthday, name FROM user WHERE uid = %# ",user.id];
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObject:fql forKey:#"q"];
[FBRequestConnection startWithGraphPath:#"/fql"
parameters:params
HTTPMethod:#"GET"
completionHandler:^(FBRequestConnection *connection,
id result,
NSError *error) {
if (error) {
NSLog(#"Error: %#", [error localizedDescription]);
} else {
NSLog(#"Result: %#", result);
}
}];
}
[self.navigationController dismissModalViewControllerAnimated:YES];
}
I'm getting value for name but null for email and birthday.
Thanks
Before you call your query, you'll need to have the user log in and ask for email and user_birthday permissions. For example:
- (BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI {
NSArray *permissions = [[NSArray alloc] initWithObjects:
#"email",
#"user_birthday",
nil];
return [FBSession openActiveSessionWithReadPermissions:permissions
allowLoginUI:allowLoginUI
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error) {
[self sessionStateChanged:session
state:state
error:error];
}];
}
The above method is used in the context of this tutorial:
https://developers.facebook.com/docs/howtos/login-with-facebook-using-ios-sdk/
Also check out the FQL tutorial:
https://developers.facebook.com/docs/howtos/run-fql-queries-ios-sdk/
I am having issues when I try to do "save" with MagicalRecord. My code:
- (void) findInternetObject {
[InternetObjectFinder runBlockSuccess:^(NSManagedObject *obj) {
obj.attr1 = #"abc";
[[NSManagedObjectContext MR_defaultContext] MR_saveErrorHandler:^(NSError *error) {
NSLog(#"failed to save attr1, Error: %#, %#", error.localizedDescription, error.userInfo);
}];
}];
}
where obj was created in method "runBlockSuccess" method in "InternetObjectFinder" class:
InternetObject *obj = [InternetObject MR_createEntity];
The app crashes at line:
[NSManagedObjectContext MR_defaultContext] MR_saveErrorHandler
with error: EXC_BAD_ACCESS
Any help is appreciated.
It seems to be a scope issue inside your nested blocks,
have you tried to write something like this (not tested):
- (void) findInternetObject {
NSManagedObjectContext *defaultContext = [NSManagedObjectContext MR_defaultContext];
[InternetObjectFinder runBlockSuccess:^(NSManagedObject *obj) {
obj.attr1 = #"abc";
[defaultContext MR_saveErrorHandler:^(NSError *error) {
NSLog(#"failed to save attr1, Error: %#, %#", error.localizedDescription, error.userInfo);
}];
}];
}
If the proble persist maybe this detailed answer can help you:
How do I avoid capturing self in blocks when implementing an API?
You should call save method on main thread. Your code looks that you are saving core data into block. If that doesn't work you can use below code to save.
MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
} completion:^(BOOL success, NSError *error) {
if(success){
NSLog(#"success");
}
}];