I hope this isn't an inappropriate post, but I wanted to make sure my first steps implementing parse as my backend are in the right direction to save some time. I'm new to both iOS programming and the parse sdk, so please bear with me!
In my app, users are able to create various polygon shape overlays on a Google Maps mapView, stored as a GMSMutablePath, which is basically a list of coordinates. Users will have at least one group of paths, each with at least one path. There will also be some information stored with each group, stored as strings or numbers. This information is specific to a single group of paths.
I'm trying to figure out the best way to store this data. My first basic question is 1) Can I store the GMSMutablePath as a whole in the Object data type? Or does the Object data type refer to a class that is created through parse? This link (https://www.parse.com/questions/what-is-data-type-of-object-in-data-browser) is the 'best' explanation I found of the Object data type, and it isn't very clear to me.
My gut instinct is no, I can't store the GMSMutablePath object, and that Object refers to a Parse object. Which leads me to 2) How should I store this data, then? I can get the individual lat/long values of the coordinates that make up each path, and I can store those as numbers, and use the numbers to recreate the paths elsewhere. None of the paths should use too many coordinates, and there shouldn't be too many paths in each group.
Playing around a little bit in the data browser, I see that I can store arrays, but I'm not sure how those are formatted, as I'd need an array (of groups) of arrays (of paths) of arrays (of lat/long values). A little bit of googling tells me it can be done, but doesn't show me how. Can any datatype be stored in any array, or is a datatype specified? I'm used to C++ programming, so I'm used to an array containing a single type of element. What I'm thinking is that I'd need an array of objects, which would be the groups of paths. Each one of those objects would have the string/number information associated with the group, as well as an array for the paths within the group. For each one of those paths, it would have to be either an array or an object. Since for the path I just need the coordinate lat/long values, I think that I can get away with an each path being an array of numbers, and I can write my program to use one array, with odd indexes being lat / even indexes being long values. That all being said, I'm not sure how to create all of that. I'm not looking for somebody to write my implementation for me, but all of the examples I can find are much more simple... if anybody could point me in the right direction to do this, or has a better idea of how to do it, I'd love some pointers.
Each user is going to have their own groups, but that data is going to be shared with others at some point. The data will be associated with the user it belongs to. With that in mind, my last question is 3) Should I store all of this information specific to a user and their groups on the User class, or make it all a separate class entirely? My guess it that I should add an Object to the User class, and store the groups within that Object. I just want to make sure I have that right, with future scalability in mind. Like, when I pull the group data, am I going to have to pull the entire User data from another user, and if so, is that going to slow things down significantly? I'm thinking that I do have to send entire user data, but I don't know if that poses any security risks. Would it be best to have a separate class for the groups, and store the user id associated with the groups? If I do this, should I also store the groups as an object on the User class?
Sorry for the wall of text, but thank you for any guidance you can provide!
If you need any clarification, let me know.
Thanks,
Jake
Creating a class to hold all the objects turned out to be unnecessary. It only had a few extra details that were just as convenient to add to the user object, and then have an array of objects on the user.
Some main things to note that I learned are: use addObject to add to an array, rather than setObject to add a single object to a PFObject/User.
Parse fetching/saving happens in background threads, so if you're loading the data to do something specific with it, make sure the code using the data occurs inside a block using the [PFObject fetchInBackgroundWithBlock] method.
Also, as changes are made to the structure of your data on a parse user/object, make sure you sign out of the current user and create a new one on your app, or you may run into lots of undefined behaviour that could crash your app.
Related
I have an app that is using Firebase quite extensively to store data that contains relationships. I want to make sure I am using Firebase as safely as possible in offline mode. The safety concern I have can be demonstrated in the following example:
Assume I have a Zoo model where each individual zoo is stored in Firebase as a subnode of "/zoos".
I have an Animal model where each individual animal is stored in Firebase as a subnode of "/animals".
A Zoo can have Animals which are stored in an ordered list. Specifically, the Zoo model contains an Animal array e.g. [Animal]. This list of Animals is stored in Firebase as a set of position-reference pairs at "/zoos/myZoo/animals" which will contain nodes like:
{0: "animals/fidoTheDog"},
{1: "animals/jillTheCat"}
When I add a new Animal to a Zoo, I need to know how many animals are currently in that zoo so I can add the new animal in the right position like:
{2: "animals/jakeTheSnake"}
If I am offline and happen to read the location "zoos/myZoo/animals" to get the list of animals so I can add in the right position, I want to make sure I have accurate data. I know that if someone else wrote to that position while I am offline and added another animal in position 2, I will get stale data and when I add an animal in position 2, I will overwrite his entry at "zoos/myZoo/animals/2" when I again go online. So that is an issue.
But, if I know I will be the only one writing to that location, can I be relatively sure that Firebase will hold the crucial data at "zoos/myZoo/animals" for me since I am using isPersistenceEnabled = true? In other words, will Firebase just keep that data in cache as long as I have recently written to that location or recently read from that location?
Or do I explicitly need to specify "keepSynced(true)" on that location? This gets to the core general version of the question - How does Firebase choose what to store in its cache with isPersistenceEnabled = true? Especially if I have not specifically set keepSynced(true) on any particular locations. Will Firebase just prioritize recently read data and then when the 10mb limit is hit, discard the old stuff first? Does it matter if I wrote the data to that location a long time ago but consistently read from that location? Will it still maintain that location in the cache because it was recently read? Will it ever discard data before hitting the 10mb limit?
I'm a little bit of a newbie so thank you for your patience with me!
-------------- FOLLOW UP QUESTIONS --------------
A couple follow up questions.
I think the approach suggested in the blog (given by Frank in comments) of using childByAutoID sounds good. So if I am saving a zoo with many animals (in order) then it sounds like I would loop through the animals and use childByAutoID to create a new key for each animal whose value will be the reference to the location of the animal object. Can I be sure that the keys that I create in rapid succession (looping will probably be very fast) will ultimately sort correctly when ordered lexicographically? I’m looking at this blog post and assuming that is the case. https://firebase.googleblog.com/2015/02/the-2120-ways-to-ensure-unique_68.html
Suppose I am doing something more complicated like inserting an animal at the beginning of the list in position zero. Then before doing the operation, I would sync down the list of animals in the zoo as suggested in the blog post you sent. https://firebase.googleblog.com/2014/04/best-practices-arrays-in-firebase.html. If the user is offline, I obviously can’t be sure that I will have the freshest copy. But suppose I am ok with that because users will only be working with their own data and only on their own device. In that case, does it help to use keepSynced(true) on the path to the zoo? Or since the amount of data the user is working with is well, well under 10mb (the whole database right now is 300k for 10ish active users), can I just assume the cache will store the data in the zoo path (whether keepSynced or not) because we never flirt with the 10mb limit in any case?
Thank you!
Hello I have The Following Problem,
I want to save my data to my realtime Database so, that I can use it as a list.
so know I am trying to save the PartyId (yellow) with a uuid (red), but this is not really working, because I need the uuid to use it on swift.
So are there probably any other ways to save or read the data.
Thanks in advance.
If you only need to store the data in an array, you need to add the index of the element as a key, and the PartyId as the value.
This make the "Array" element to be able to be treated as an array when you retrieve the data.
Just to be mentioned, if you need to make some queries when you retrieve the data (for example, how many users assist to a specific party) consider to flatten your structure data like this:
With this you can be able to query, for example, all the users that have a specific partyId. For more information, you can check the documentation to create good data structures
As far as I know, there is no way of setting an entity's attribute as unique through Core Data, neither programmatically nor in Xcode's editor... I need to make sure that certain managed objects can't be created if there are collisions with the values of the attributes I want to be unique, and I've been reading some posts dealing with that.
I've found a couple of approaches (e.g. Core Data unique attributes):
To use -validateValue:forKey:error:
To write some kind of custom method to check if the attribute's value already exists
What should the most recommendable option be?
Thanks
You're going to need some kind of custom code, whether you put it in validateValue:forKey:error: or in a custom method or somewhere else.
Whether to use the built-in validation method is really a matter of how you prefer to organize your code. I'd prefer to do something like
Check to see if the value is unique.
If so, then insert a new instance.
That's partly because I find the built-in validation scheme to be a pain, but mostly it's because that code will run every time you save changes to an object. If your check is in validateValue:forKey:error:, you'll run it repeatedly, even after you've verified that the value is unique. Then again maybe you need to do that, so the best answer in your case depends on a bigger picture of how your app needs to work.
The simple way to approach validation is by doing a fetch with a predicate identifying the key and value that you need to check. The one change I'd make to the common fetching approach as described in the other answer is that I'd use countForFetchRequest:error: instead of executeFetchRequest:error:. It doesn't sound like you actually need to fetch existing objects during validation, you just need to know whether any exist, so just check that.
Depending on the type of the unique attribute, you may be able to reduce the performance hit that you're going to take by doing this. For example, if it's a string. Checking all existing strings for a match is relatively expensive. On the other hand checking a bunch of existing integers is cheap. In that case you might find it worthwhile to add a numeric property to your entity type that stores a numeric hash of the unique string value. Use the hash only when checking uniqueness. It'll be a hell of a lot faster than looking for matching strings, and NSString even has a handy hash method to calculate the value for you.
I'd like to able to get a unique ID for an object so that I can later test another object against it, without having to keep the first object. Say I have an NSArray of NSDictionaries that describes some sort of playlist (not the best way to store data but for arguments sake). Its too big to store, and the user may have many of them; everytime the user uses the application I just download it again. I want to be able to offer the user the ability to continue the playlist from his last location but only if the playlist is exactly the same (say its some sort of feed that updates regularly, but always has the same count). Is there some sort of quick way to ID that object into a small'fingerprint' object, and then test the new playlists fingerprint against it? Obviously it doesn't have to be perfect (otherwise it would be the whole object), just something unique enough to test 'likely' equality. (Note: I'd prefer a solution that worked for any NSObject-not just an NSArray of NSDictionaries).
My naive approach was to just concatenate the first the first three letters of all of the NSStrings in each NSDictionary - that seems silly.
This question is about why I would use the above keywords. I've found plenty of MSDN pages that explain how. I'm looking for the why.
What query would I be trying to write that means I need them? I ask because the examples I have found appear to be achievable in other ways...
To try and figure it out myself, I created a very simple entity model using the Employee and EmployeePayHistory tables from the AdventureWorks database.
One example I saw online demonstrated something similar to the following Entity SQL:
SELECT VALUE
DEREF(CREATEREF(AdventureWorksEntities3.Employee, row(h.EmployeeID))).HireDate
FROM
AdventureWorksEntities3.EmployeePayHistory as h
This seems to pull back the HireDate without having to specify a join?
Why is this better than the SQL below (that appears to do exactly the same thing)?
SELECT VALUE
h.Employee.HireDate
FROM
AdventureWorksEntities3.EmployeePayHistory as h
Looking at the above two statements, I can't work out what extra the CREATEREF, DEREF bit is adding since I appear to be able to get at what I want without them.
I'm assuming I have just not found the scenarios that demostrate the purpose. I'm assuming there are scenarios where using these keywords is either simpler or is the only way to accomplish the required result.
What I can't find is the scenarios....
Can anyone fill in the gap? I don't need entire sets of SQL. I just need a starting point to play with i.e. a brief description of a scenario or two... I can expand on that myself.
Look at this post
One of the benefits of references is that it can be thought as a ‘lightweight’ entity in which we don’t need to spend resources in creating and maintaining the full entity state/values until it is really necessary. Once you have a ref to an entity, you can dereference it by using DEREF expression or by just invoking a property of the entity
TL;DR - REF/DEREF are similar to C++ pointers. It they are references to persisted entities (not entities which have not be saved to a data source).
Why would you use such a thing?: A reference to an entity uses less memory than having the DEFEF'ed (or expanded; or filled; or instantiated) entity. This may come in handy if you have a bunch of records that have image information and image data (4GB Files stored in the database). If you didn't use a REF, and you pulled back 10 of these entities just to get the image meta-data, then you'd quickly fill up your memory.
I know, I know. It'd be easier just to pull back the metadata in your query, but then you lose the point of what REF is good for :-D