How can I store array that contains PFObjects in NSUserDefaults? - parse-platform

Some PFObject contains PFFile(Image file) and some are not.When I am trying to store custom object in to user default using NSKeyedArchiver and NSKeyedUnarchiver, it won't work.
Help me how to store PFObjects array into UserDefault which contains PFFile type field.

From NSUserDefaults documentation:
A default object must be a property list, that is, an instance of (or for collections a combination of instances of): NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. If you want to store any other type of object, you should typically archive it to create an instance of NSData.
So you can get your file's data by getDataInBackgroundWithBlock and save it to NSUserDefaults:
[file getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
[[NSUserDefaults standardUserDefaults] setObject:data forKey:#"file"];
[[NSUserDefaults standardUserDefaults] synchronize];
}];
There is also a library called Parse-NSCoding which adds NSCoding extension to Parse objects. It is not updated but you may check it out.

Related

Query with pointer User in Parse.com

I am using Parse.com in my app, I have created a "Post" class and inside I have a pointer that specifies which user sent the post. Now I seeing on the timeline to the Post and the time the user name who created the post. Since the user is a pointer I can not make a correct query, do you know how can I fix this issue?
The trick is to use PFQuery includeKey to have the related pointer data automatically filled by Parse.
The user data will be downloaded without requiring you to make another query for it.
PFQuery *query = [PFQuery queryWithClassName:#"Post"];
// Include the user data with each post
[query includeKey:#"title_of_userpointer_column"];
[query findObjectsInBackgroundWithBlock:^(NSArray *postObjects, NSError *error)
{
if (!error) {
NSLog(#"Successfully retrieved: %d items", [postObjects count]);
// postObjects now contains the latest 100 Posts, and the "title_of_userpointer_column" field
// has been populated.
// For example:
for (PFObject * postObject in postObjects) {
// This does not require a network access.
PFObject *postAuthor = [postObject objectForKey:#"title_of_userpointer_column"];
NSLog(#"retrieved related Post Author: %#", postAuthor);
}
}
You can retrieve the pointer to User field from the Post table by adding this line of code (in Android):
postQuery.include("pointerToUser");
postQuery is query of class Post. By this way, after executing the query the object or objects that will be returned would have the user information.
You can see a full example here:
How to query value of column that is set as pointer to other table in Parse

moveRowAtIndexPath and CoreData Relationships

I'm stuck at ordering Core Data relationships. I have a to-many relationship but the problem I can't overcome is that re-ordering relational entities in one view re-orders them in every view they belong to.
Example: People are added to activity1 and are randomly ordered using the moveRowAtIndexPath method. Those same people get added to activity2 and are ordered identically to activity1. How can I stop this?
Relevant code:
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
NSUInteger fromRow = [fromIndexPath row];
NSUInteger toRow = [toIndexPath row];
id object = [[eventAthletes objectAtIndex:fromRow] retain];
[eventAthletes removeObjectAtIndex:fromRow];
[eventAthletes insertObject:object atIndex:toRow];
int i = 0;
for (object in eventAthletes)
{
[object setValue:[NSNumber numberWithInt:i++] forKey:#"athleteDisplayOrder"];
}
[self saveContext];
[object release];
}
I updated the model and made the attribute athleteDisplayOrder transient thinking that by using the key and NOT saving it, I would be able to start fresh in a new event. No Dice.
The identical ordering is expected behavior. If you want to "randomize" the order, you have to explicitly do that by reassigning random athleteDisplayOrderattributes.
EDIT:
If you want to have a special user definable order of athletes for each event one way to solve this is to create a new entity EventAthletes that has to-one relationships both Event and Athlete and also contains a display order attribute.
END EDIT
BTW, you are using an extra data array with core data for display in a table view. Did you know that you can use NSFetchedResultsController to manage your table view datasource much more efficiently?

Saving changes to a NSManagedObject

I have a problem with making changes to ManagedObjects and saving those changes to the persistent store.
What does work is deleting objects, inserting object. and fetching those objects. As said, i fail making a change to a fetched managed object.
I have two view controllers.
Both have a public property:
#property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;
The AppDelegate.m file sets this property for the first view controller in the application:didFinishLaunchingWithOptions: method like so:
// get reference to view controller //
//..
controller1.managedObjectContext = self.managedObjectContext;
view controller1 again passes the managedObjectContext when pushing to the second view controller, it does this in the prepareForSegue: method like so:
// Get reference to the detail view //
MySecondViewController *controller2 = segue.destinationViewController;
// Pass the managed object context //
controller2.managedObjectContext = self.managedObjectContext;
Within this second view controller I fetch objects from core data and I store them in a property of the view controller like this:
#property (nonatomic, strong) MyKindOfObject *object;
...
self.object = [fetchResults lastObject];
Fetching objects seems to work fine as i nicely get results..
The fetched object has a number of properties, one of them is of type NSString. The value of this property I show in a UITextField. The user can change the value here and when done he presses a button. I catch the action and I do the following:
self.object.mytext = textField.text;
followed by trying to save to core data:
// Save to CoreData //
NSError *error = nil;
if(![self.managedObjectContext save:&error]){
// handle the error //
NSLog(#"is error");
}
else{
NSLog(#"no error");
}
1) The next time the user returns to this view controller, again the object will be fetched. But it still has the old value.
2) Also I use a Firefox add-on called SQLite Manager to keep an eye on the data within the related sqlite file. When stepping through the code, after calling the save method nothing changes in the file.
3) Also within Xcode i use the Variables View to keep an eye on the self.managedObjectContext object. When I am storing the new data into my object, right before calling save, none of the properties of self.managedObjectContext change (like unprocessedChanges or changedObjects).
4) I also added a call to the hasChanges method of the managedObjectContext, but this returns NO:
if([self.managedObjectContext hasChanges]){
NSLog(#"changes managed object context!");
}
5) I also added a call to the hasChanges method of the related managedObject, but this also returns NO:
if([self.object hasChanges]){
NSLog(#"changes in managed object!");
}
I am probably doing something totally wrong here but I can not figure out what it is.
I truly hope somebody can help me out?.
Thanks in advance!
Oke let me answer my own question: as the newby that I am, i indeed did something totally wrong. I was thinking I knew better then apple themselves. lesson learned: I do not!
After creating entities within the model I created custom managed object classes for each entity (or actually NSManagedObject subclasses for each entity).
Within the generated implementation files all properties (attributes) are implemented as #dynamic. Due to lack of knowledge I did not understand/recognise this. So the newby in me thought: lets change all that to #synthesize.
Hopefully this post can help some other newby to not make the same mistake.

Create entity programmatically and add it to an array controller

I have an array controller which is bound to an nstableview. I also have some nstextfields which the user populates then presses an "add" button. I want to take those fields, first_name and last_name, and use them to populate an entity. I'll call the entity PersonEntity.
So in the delegate for the add button I get the string values for the 2 text fields, populate an entity, then add it to the array controller. I'm new to cocoa/objective-c. This seems like a straightforward thing but it appears that I cannot create an entity like I expect
PersonEntity* person
[person setFirst_name:firstName];
[person setLast_name:lastName];
[customerArray addObject:person];
It crashes saying I can't add nil at the [customerArray addObject:customer] line. That line is my attempt to add the entity to the array controller which is bound to the tableview. What is the correct way to do something like this?
I'm not sure if PersonEntity is a Core Data Entity, but since you question is also tagged as Core Data, I'll assume it is.
If your ArrayController (the one bound to your NSTableView), is bound to CoreData source, you don't add objects directly to it. Instead you add it to your managedObjectContext and it will reflect on your NSTableView.
The code should look like this:
PersonEntity *person = [NSEntityDescription insertNewObjectForEntityForName:#"PersonEntity"
inManagedObjectContext: managedObjectContext];
[person setFirst_name:firstName];
[person setLast_name:lastName];
/* Save Event */
NSError * error = nil;
[__managedObjectContext save: &error];
Hope this helps!
Mane

Iterate through NSManagedObjectContext objects?

I want to iterate through all of the objects in my NSManagedObjectContext, and update them manually. Then, every managed object should be updated.
What's the best way to do this?
Theoretically you could iterate through all the entity descriptions in your managed object model, build a no-predicate fetch request for them, then loop over all the returned objects and do some update. Example:
// Given some NSManagedObjectContext *context
NSManagedObjectModel *model = [[context persistentStoreCoordinator]
managedObjectModel];
for(NSEntityDescription *entity in [model entities]) {
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entity];
NSError *error;
NSArray *results = [context executeFetchRequest:request error:&error];
// Error-checking here...
for(NSManagedObject *object in results) {
// Do your updates here
}
}
Note you can cast the NSManagedObjects returned as necessary either by testing for class equality (using isKindOfClass: or a related method) or by figuring out what class the current entity is (using the managedObjectClassName property on entity in conjunction with the NSClassWithName() method).
This seems like a very heavy handed approach to the problem. If the data is getting loaded with bad data then i would strongly suggest fixing it while you are importing the data. Tim's answer will work for what you are doing but I strongly suspect you are coming at this wrong. Iterrating through the whole database looking for potentially bad data is very inefficient.
If managed objects are getting created with the 'wrong data', I would check to make sure you've set default values in your model for all properties of all entities. This way you can be sure whenever you insert an object into your context it will contain those values. From there, you can set the properties to whatever you need.

Resources