I have a bunch of game data (10 integers) I need to save and load.
Is it more efficient to use a NSMutableDictionary, add the items and save it, or to save each item into NSUserDefaults?(NSMutableDictionary is already created, when the data is loaded in on startup)
The same question goes for the loading, is it faster to load the dictionary and then extract the data, or just get each one from NSUserDefaults one at a time?
A benefit of NSUserDefaults is obviously the global access.
This is a trifling amount of data and relative efficiency doesn't even come into it. Go for the simplest code in this case, which is user defaults.
Related
I have quite a broaden app in which I store lots of data. CLLocation ones, Arrays, CGPoints and so on. From time to time there's a need to save all these variables on the device, so I use UserDefaults. Yet, after some time of switching through ViewControllers and simply using the app (constant changing of data => constant saving it) I get to the point where everything runs slowly.
Now, suppose I have more or less three 2-dimensional Arrays and lets say 5 Ints I want to save to UserDefaults.
Every time I change one of the variables I "update" it by the same command:
UserDefaults.standard.set(data, forKey: "UDdata").
So every time I want the data to change, I change it through that particular comment. I guess every time I do it I should somehow get rid of the previous data for key UDdata and just then set it with the same key string? Information on that matter would be useful. Thanks in advance
The reason is you misusing the Userdefaults. They are to store small values like flags to detect first launches, preference and etc. Instead of storing data in Userdefaults just try to use CoreData or SQLite. Which is way more easier to use too.
CoreData :
https://www.raywenderlich.com/145809/getting-started-core-data-tutorial
SQLite :
https://www.raywenderlich.com/123579/sqlite-tutorial-swift
q) what is the best method of storing persons complete details i.e.
steve > details contain :name address,dob, other details etc..
john > details contain :name address,dob, other details etc..
and many more records max would be around 200 tops.
now i want to display these individually and with the option to add them what is the suggested way?
i had a look at core data,userdefaults and NSFileManager but not sure what would be best way to implement such nested texts for save and load.
if you want to search or query them I would always recommend going with core data from the get go.
You'll only end up wishing you add gone down that route in a few months and then would have to factor in a migration.
For core data I use https://github.com/magicalpanda/MagicalRecord for new projects, it does most of the heavy lifting for you.
For a recent app I used NSUserDefaults. Basically keeping all my 'person' objects as NSDictionaries in an NSArray. This suited the app as the data was low, c100 records in use max.
I could just as easily have used a save to disk method, but as I did't have any other use for saving small amounts of preference data, it was just a convenience.
(remember, accessing NSUserDefaults brings back all its contents, not just the particular object you are interested in).
Hope this helps.
I've been using app delegate interface variables through-out my app to quickly access app wide bits of data.
I believe this is causing efficiency issues in my app. And I've finally decided to move to NSUserDefaults. Unless you suggest some other way ?
Often I will want to access the same variable through-out a view, so it doesn't make sense to access this variable using NSUserDefaults each time. I figure it will be slow.
So I'm thinking a class which will read all the values into an array of some kind, in viewDidLoad and then if a value is altered, save / synchronize and update the class variable.
But if I push to a view, I guess I'm going to have to save then too.
This is beginning to sound a bit messy.
However, I'm just wondering what approach will be efficient and easy to use ?
A shared Model object (using the MVC paradigm) is the usual recommended way to share variables to multiple other objects or classes. This Model object can be a singleton, or other objects can locally copy or be delegated a reference to a single Model object for fast access to its getters/setters.
The fastest variables access method is often just using C global variables (since regular C is a subset of Objective C), if you are willing to deal with potentially more difficult code reuse and debugging problems.
NSUserDefaults is just using the file system as a key-value dictionary global variable. Slow, and with the many of same structure problems as C global variable use.
It really depends on the size of data you're accessing. The serialization of several NSDictionary objects to disk may be enough to cause your app to lag.
If you're serious about iOS development, you should learn to use Core Data. Anything NSUserDefaults can do, Core Data does better. The only one advantage NSUserDefaults provides reduces lines of code in tiny one-off apps. Think of Core Data like laying the foundations for a house, and NSUserDefaults like pitching up a tent.
If you need to use variables like arrays or sets you'd better not use NSUserDefaults since on synchronize they save all stored values onto disk (of course if you don't need storing them to disk). If you need to store large amounts of data in object graphs with relations like this
User
-name
-lastname
-email
-messages
Message
-date
-text
Then you'd better start looking into CoreData framework, it's very easy to use and allows to store large data sets to disk and access them quickly.
If you just need some class that would, for instance, store current user profile values like username, email etc. Try creating a singleton class - which is quite the same as using AppDelegate, but it's much clearer to use when you're separating your data into smaller chunks.
Anyways I wrote this answer based on my assumptions only. It would be nice to know what data kinds you are working with and what is its lifecycle in your app.
I would like to make a data manager class that retrieves data from plist, and I wonder if I should make a class with all class methods which read plist every time when the method is called and returns requested value, or create a class initializer which initializes an array(instance variable) with the plist data and all methods are instance methods which get data from the array.
I would like to know which is more expensive:reading plist many times (like 50 times) or instantiating an object, or simply which is better.
Thank you for your help in advance.
This is one of the classical tradeoffs in programming - speed vs. memory use. The technique of reading something once and storing it on a faster medium (in this example, in memory) is called caching. It's very popular, and for good reason. Mass storage devices are still magnitudes slower than RAM, and network access is magnitudes slower than local mass storage.
If you assume the data will be asked of the manager often, and if you assume the plist won't change (or you can detect changes), then read the plist on the first access to the getter, store it in an iVar, and answer only the iVar as long as the plist hasn't changed. This uses a little more memory, but is a lot faster for subsequent accesses.
NOTE: This approach would be harmful for very, very large files. If you are concerned about memory usage, implement the - (void)didReceiveMemoryWarning method in your viewControllers, and flush the cache (delete it) when you are low on memory.
A getter method could look like this:
- (NSArray *)data
{
if (!cacheArray) {
//what we do now is called "lazy initialization": we initialize our array only when we first need the data.
//This is elegant, because it ensures the data will always be there when you ask for it,
//but we don't need to initialize for data that might never be needed, and we automatically re-fill the array in case it has been deleted (for instance because of low memory)
cacheArray = ... //read array from plist here; be sure to retain or copy it
}
return cacheArray;
}
I'm loading in data from an sqlite database, storing the values i load from there in the instance variables of a custom class, and then adding this class to a mutable array, which i'm then assigning to the instance variable of my view controller, for use in a tableview.
I would, though, like to save this array into a .plist file in the documents directory on the app's first run, so that i can retrieve the whole object from there on load, rather than pulling all 214 items from the database.
Is this approach a better option? if so, could someone please help provide me with some code that will allow me to save an array of my custom classes as a .plist file? I've come across a lot of sample code on the web, but none of it works correctly.
I'd like to:
Check for the existence of the my_data.plist file.
If it exists, read it in as the array.
If it doesn't, read the data from the sqlite db into an array.
save this data to a .plist so that it can be read in faster later.
Thanks guys, appreciate any help you can give me.
It will probably be faster to just get the values from your database on launch. There will almost definitely be more cost to parse a plist containing these values than to just get them all from the database, unless the query you have to use to get them from the database is really slow.
Note also that once you're saving these objects to a plist on disk, you're actually going to be hurting performance of your program because you'll be writing your objects to disk twice and reading them from disk twice. You'll also be introducing opportunities for discrepancies between the plist and the database in the event of a bug or a crash.
That said, the only way to prove this to yourself may be to implement and profile both options, and compare actual numbers. Check out #occulus's link, above, for instructions how to read and write a plist. To profile your app, try using Instruments
When I google for "nsarray writetofile custom object" (no quotes) and click on the first link in the results, I find a really useful page.
For the record, it's this:
http://www.cocoabuilder.com/archive/cocoa/240775-saving-nsarray-of-custom-objects.html