I need store just 10 arrays in my app, which I can change from time to time. What would the best way to do this be?
I have been looking into writing to a plist, is this a good idea?
Each of the 10 arrays will have 10 objects (just strings).
You could create an NSDictionary (or rather the mutable version in your case) and populate it with your arrays. Then you could write them to disk with
writeToFile:atomically:
At start you could check whether your path is valid (meaning your dict exists) and assign it to your iVar in code for example with
initWithContentsOfFile:
The advantage is that the underlying representation is a plist for the NSDictionary (or NSMutableDictionary). So you are good to go here as well and as your objects within the arrays conform to NSCoding they all know how to encode them for writing to disk.
Using a plist file is a fine way to go as long as you don't need to interoperate with a non-Objective-C codebase (e.g. share with a Windows app, send the data to a server, etc.)
Related
I am working on an application for the iPhone (iOS 5). What I have to do is create a map by using binary data that I reveive from a server. If the server has bytes available, I read them into a buffer: uint8_t[1024]. Then I parse through this data and create objects (e.g. a path that contains points with longitude and latitude) from it, but those objects are often larger than my buffer. On the simulator this is not a huge problem, because I have enough memory to store them into mutable arrays.
But how do I have to handle this to make my application safe for a device? What array size should I use for iOS devices?
I hope my issue was understandable.
You can use NSMutableArray and store data temporarily and expand its size as needed.
Hope this helps.
Have you considered using NSData (or its mutable subclass NSMutableData) instead?
These provide an object wrapper for byte buffers, and can be grown arbitrarily using the appendData: selector.
From the documentation:
NSMutableData (and its superclass NSData) provide data objects, object-oriented wrappers for byte buffers. Data objects let simple allocated buffers (that is, data with no embedded pointers) take on the behavior of Foundation objects.
That said, if you're only allocating on the order of kilobytes you're not likely to face memory issues.
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.
For my current app I'm using the NSKeyedArchiver approach to persist my objects to the iPhone between launches. I'm wondering if it makes sense to tag this file when it's created with a version number so that in the future when the app revs we'll know what kind of data we're dealing with should migration be necessary. Is this recommended for something as simple as an NSArray of custom objects that are serialized with NSKeyedArchiver? If so how/where to stash the version number?
Thanks!
If you feel like the format will change, then yes, you'll want some way to detect which version of the file you're working with. A simple way to do this (since you're using NSArray) would be to simply add the version number as an NSNumber to either the beginning or end of the array. Alternatively, for a more complicated approach that doesn't actually change the files, you could store the information in a separate file (say, using an NSDictionary that links the file name and version number). Or, you could use the user defaults system to store it, and if it's frome an older version, update the file and the user defaults key.
I wouldn't use the second method, unless you're dealing with multiple keyed data files. Of those three, I'd probably choose the last, but there may be some other way to do it that makes more sense.
I want to ship some default data with my app. This data can be stored perfectly in a property list. The strucure is simple:
Root
0
animalType = cat
animalName = Tom
1
animalType = dog
animalName = Rambo
I thought: When I use a property list rather than hard-coding it somewhere, then I could easily provide more defaults to choose from after the app is distributed already. If I would hard-code it, I would have to provide heavy upgrades every time, and Apple would take weeks to let them pass.
But there's one thing I don't get. I make that property list manually in Xcode and put that in my Resources group. As far as I know, Xcode would compile it into some binary format. In my app I would use NSPropertyListSerialization to create a NSDictionary out of it. But this property list would not get placed into the documents directory of the sandbox, right? So if the application would download an update of that property list some time in the future, the update would have to go into documents dir, but the app would still look at the old plist in the root, right? Where to put it? Must I copy it to documents, just like an sqlite database?
And the other thing: When I edit the plist and provide the whole thing as an XML for download/update from a server, then of course that thing would not be "compiled" into some binary format. How would that work? Would NSPropertyListSerialization have trouble reading it? Must I compile that thing every time with XCode and let the app download some binary stuff?
There are two commonly used property list formats: proprientary binary format and xml format (DTD). You can use either of them, and NSPropertyListSerialization will detect automatically, which one is used for your data when de-seralizing.
XML format is more verbose, but it's simple to generate. If you're publishing data from server, you might consider generating xml plist, and compress it with gzip or something.
Now to your first question about where to store the data. To make application payload smaller you might first check documents directory for updated plist, and if it is not present - load default plist from your application bundle.
One general approach used is to always copy plists or other updated elements into the application documents directory - then you just always load from there, and replace when there is an update.
Or you could pre-load the data into a database, download plist updates and refresh the database entries at that time.
I would appreciate some help with something I working on and have not done before now and having some proplems because I don't think I understand exactly how to do this. What I'm wanting to do i'm sure is simple to most all of you and will be to me as soon as I do it the first time correctly....anyway.... I have a tableview that I'm needing to populate with two things, a username and a number with a count of items (the username could be a primary key). Currently I have a tableview populating and editable with an array....no problem....I know how to do that.
The two parts I need help with understanding is to:
read a plist with these two values into a dictionary, and read them into two different arrays that I can use with my tables.
Save the arrays back to the dictionary and then back to a plist.
I think I'm getting the most confused with how to store these two things in dictonary keys and values. I've looked that over but just not "getting it".
I would appreciate some short code examples of how to do this or a better way to accomplish the same thing.
As always, thanks for your awesome help....
You can use NSArray method writeToFile: atomically: to dump your data into a file, you can then use initWithContentOfFile to retrieve the information from t hat file just as you dumped it previosly. I believe if you have dictionaries in your array you should be able to get them back this way. You can always use core data as well for storage if you find your structures to store are getting complex and dumping the in a file and getting them back to recreate some o bjects is becoming messy.
The approach that would perhaps be the simplest is to store the data as an array of dictionaries. This has the issue that recreating the array from a plist with mutable leaves is convoluted at best.
But if you can tolerate the performance hit of replacing dictionaries when updating the list instead of modifying them, it might definitely be the simplest course of action.
This also has the added benefit that your datasource only needs to deal with one array, and that the whole shebang would be Key-Value Compliant, which might further simplify your code.