Writing a PFObject to disk - ios

When I looked up how to write a PFObject to disk, I found some quite complicated stuff.
The simplest option I found was to write encoding and decoding functions and then use NSKeyedArchiver (which I have not tried yet because I want to make sure I'm using the most adequate solution).
More complicated options involved third-party libraries so as to sync with Core Data.
Parse.com engineers said they are working on features that will make offline usage work better, but nothing is there yet AFAIK.
However, the PFUser class has a currentUser method with the following description and signature:
/*!
Gets the currently logged in user from disk and returns an instance of it.
#result Returns a PFUser that is the currently logged in user. If there is none, returns nil.
*/
+ (instancetype)currentUser;
It seems that whatever is in this method should be a good way to work with a PFObject on disk.
Is there any way to know what the technology behind this method (and behind all the logIn*methods in which the saving must be happening)?

Apparently PFUser.currentUser() actually just returns a static class variable, as seen here.

Related

Pulling Data of Pointer Field of PFUser.currentUser in Parse

I am writing an iOS app with Swift using Parse.
In my User table, I have a pointer field called UserAddress which is pointing to an Address table record. I would like to pull this Address data for current user. I did a bit of research and figured out fetching in background is an option but I would like to avoid it. Is there an alternative to pull this data without running extra fetch work?
What I can imagine is:
Fetching pointer data in AppDelegate before the app gets ready to use for users.
Somehow, force to set includeKey when loading a currentUser
Any of the above is feasible? Please advise me.
You correctly understand the two options, and they are the only two options. For non-user objects, usually includeKey() on a query is the way to go.
For the current user, since you have the user already, it would seem a little strange to query the user, including the pointer, just to avoid fetching the pointer, but that would work. You might be better off working on whatever's making you hesitant to do the fetch().

How to use subclass of NSManagedObject?

I'm working on a quite large app on iOS. Up until now, I've been using CoreData like this:
Have a class, that have methods like -(NSArray*)getAllEntries, or -(void)saveEntry:(Entry *)entry, and Entry has a few properties like strings, dictionaries, arrays of other objects that might or might not be saved in CoreData, etc. Mostly, I init Entry with its default ctor, and set values to properties by fetching values from the NSManagedObject by using valueForKey: I get from the CD store.
I started coding like this because at the time I was new to obj-c and I come from a C++/Java background.
Now, I'm working on a new module in the app and want to do everything the obj-c way.
As I understood, if making the Entry object a subclass of NSManagedObject, I could only init it using [NSEntityDescription insertNewObjectForEntityForName:#"Entries" inManagedObjectContext:context];, which means it would be tied to the entity? The thing is, that I might want to for example init that object from the data that I pull from the internet and I might not want to save it to the persistent store. Or, I might want to fetch the object out of the store, edit the values, but not save it to the store. Everything would be fine (probably), but as I understand, if I call the save method on the context which was used to instantiate the object, the object will be saved to the store that I didn't want to be saved.
So now I'm a little confused on how should I continue doing this. Is my old way of doing Core Data Ok, or should I use the subclass of NSManagedObject and use some tricks that I don't know of yet? And if the latter, what are those tricks?
Link answers are discouraged, but you really want to read Apple's extensive documentation on Core Data. Specifically, google for "Creating and Modifying Custom Managed Objects".
(Currently found at this link.)

Is it possible for an attacker to maliciously modify iOS keychain data?

I am storing secure data in the keychain that should be maintained only within my app. During app running this data is retrieved to some variable. It seems like it is possible to crack my app in order to read that value or even dump the whole keychain, but my question is it possible to the "hacker" modify that data i.e. modify at runtime area of RAM that holds this variable and make my app to update keychain with new value? And I also have setter method for that property, which saves it to keychain, is it possible to investigate the address of that function and force call my method with custom value?
I already looked here and here for best practices, read answer at Quora, that and that articles, looked for ios-keychain-analyzer project at GitHub but there is no mention about changing data, only about reading

Parse's CurrentUser doesn't keep refreshed data

Using Parse for iOS, I modified the _User's table to have a field called "Friends" which is an array of pointers to other _Users (by the way, I also have other additional fields).
When I call PFUser.currentUser(), I don't see this friends field in the user object. So I call PFUser.currentUser().fetch() (because refresh method doesn't seem to exist anymore) and I finally have the friends field in my currentUser object.
However, as soon as I exit the app, this field is lost. It doesn't seem to be saved locally unlike all the other fields of the current user.
How am I supposed to force a refresh of the cached current user ?
According to parse.com itself and one of their posts, there is no other way to keep your user up-to-date:
saveEventually does not write through any caches at this time,
including the currentUser, if the app has been restarted. You'll need
to regularly call fetch to keep it up-to-date. We are aware that this
is inconvenient, and are looking into ways to make it work better for
you.
Are you sure that you want your user objects to contain a value that's an array like that? I obviously don't know your use application, but I would recommend using a PFRelation instead. It works just like an array, but the Parse Framework provides a bunch of additional functionality along with it.
As for your specific question it might have to deal with Parse. Maybe they don't automatically retrieve and save arrays that are on an object. That would be my guess because an array could contain who knows how much data in it. I still don't know why they wouldn't locally save that data after it's fetched.
My suggestion is probably a little over the top, but would most likely be the best outcome. Utilize a local database such as CoreData or even the ParseLocalDatastore. Then encapsulate the Parse framework to have your own User object where you can store the information, which can also maintain persistence via your database.

Suggestion for CoreData and object handling

I need a suggestios on how to correctly implement CoreData with objects that can be uploaded/downloaded from server and sent through game center.
The app is similar to a trading card game, you can get the idea from these 2 separate entities:
Card: The actual unique cards with all the information about each one. The "Card"s entities are static and do not change, they do not need to be sent on server either because all I need to do is send the "CardId" to pull a "Card" entity.
UserCard: All the cards that a user owns, a user may have the same card multiple times but this would be a different "UserCard" with a pointer ("CardId") to a basic "Card". They are always changing. They need to be easily sent through GameCenter and uploaded/downloaded from server. Also, some temporary "UserCard"s would need to be downloaded from server when the user visits a friend's profile to see which cards they have.
Does anyone have any suggestion on how to do this correctly? Currently I have two ideas:
A. Use CoreData for everything, this would mean that the "UserCard"s are NSManagedObject subclasses which get intelligently encoded/decoded (using NSCoding) to upload/download and send through GameCenter. The basic "Card" is set as a relationship in Core Data. A "temporary" attribute is also set for the "UserCard"s to be able to know which ones do not belong to the current user so they can be deleted later.
B. Use CoreData only for the Basic "Card"s and use a NSObject subclass for the "UserCard"s. This allows me to directly use the "UserCard"s without the need to insert them into CoreData. Makes it easier to download/upload and send through GameCenter. It also removes the need for the "temporary" property because the objects will just be deallocated when the view has stopped using them. The problem with this method is that I would need another way to store the current user's "UserCard"s in the device because they do need to be available offline.
Thank you!
Personally, I would use CoreData all around. Reasons:
You're already having to dive into CoreData to deal with Cards anyways
Just create an NSManagedObject category called NSManagedObject+JSON. In it have a simple method called -(NSDictionary*)jsonRepresentation and have the UserCard format itself into a dictionary and return itself. Super easy.
It would be safer to use CoreData and save often, rather than run the risk of writing to a file and it either: 1. getting corrupted (highly unlikely but user would be mad if it did); or 2. not getting fully written (user could kill the app before it has time to write everything to a file)
The extra little bit of work to implement the UserCard entity would be small.
You get the built memory management and searching functions of CoreData.
I just finished a large project working with CoreData so I may be a little biased. From what you've stated in your question though, I would take CoreData for everything. Here are some helpful opensource libraries when dealing with CoreData and a web server:
MagicalRecord
AFIncrementalStore
And a great tutorial for integrating CoreData with a web server.

Resources