Windows 8 Apps - plist equivalent to hold dictionaries - microsoft-metro

In iOS plist files are useful resources since you can hold an array or a dictionary inside it and read from the plist file using a code like this:
NSMutableDictionary *myDic = [[NSMutableDictionary alloc]
initWithContentsOfFile:path];
Is there any structure to have a similar behavior in a Windows 8 App using C++/Cx

If you are looking for Dictionary data structure you can use:
Dictionary<TKey, TValue>
// simple example, dictionary of Uris
Dictionary<string, Uri>
// or advanced example, dictionary of lists of strings
Dictionary<string, List<string>>
Or if you're looking for a place where to save application settings, you can use ApplicationData.Current.LocalSettings. Note you can save only primitive types in there and each entry must be smaller than about 4kB.
If You want to preserve larger data in your app, like configuration object or list of favorite items, you have to save them into ApplicationData.Current.LocalFolder serialized into Json for instance.

Related

How to use my Class with PList in objective-c?

I have a Class for handling my data in my project, and now I need to store the data.
I'd like to use a Plist but I'm a bit unsure of how to start.
My class is pretty simple - 6 pieces of data, flat (no hierarchy).
I want my app to start with no data, so can I assume that I should create the PList programmatically once the User creates their first piece of data? (That is, don't create a .plist file in 'Supporting Files' prior to distribution?)
Then, when the app starts the next time, read the data and create an NSMUtableArray array of Class instances?
To create a property list, all you need to do is use appropriate types (i.e. those that support the property list format: NSData, NSString, NSDictionary, NSNumber, NSDate, NSArray), store them in a single container, and tell the containing object to write itself to a file. To read the data, you can initialize that same type using a path. For example:
// writing some data to a property list
NSString *somePath = ... // replace ... with the path where you want to store the plist file
NSMutableDictionary myDict = [NSMutableDictionary dictionary];
[myDict setObject:#"Caleb" forKey:#"name"];
[myDict setObject:[NSNumber numberWithInt:240] forKey:#"cholesterolOrIQ"];
[myDict writeToFile:somePath atomically:YES];
// reading the file again
NSDictionary *readDict = [NSDictionary dictionaryWithContentsOfFile:somePath];
The simplest way is to simple save an NSArray or NSDictionary to disk. Caleb's answer goes into detail there so I won't repeat it, other than to say you might have to convert a non-compatible object like NSColor to an property list object like NSData. It's up to you to do this each time you save or load your data.
NSKeyedArchiver and NSKeyedUnarchiver give you a little more control over the process, but work pretty much the same way. You provide (or get back) a plist compatible root object (usually an NSDictionary) that contains your data. I recommend creating a dictionary that includes your data structure as well as an arbitrary number (your app's build number is a good choice) to use as a version indicator. This way if you ever update your data model you can easily determine if you need to do anything to convert it to the new version.
If you're putting your own objects into the data file, look into NSCoding. The protocol gives you two methods using NSKeyedArchiver and NSKeyedUnarchiver to save and restore your data. This is by far the most straightforward approach if your data model consists of anything more than a few simple strings and numbers, since you're dealing with your own native objects. In your case, you would have your data class implement NSCoding and use the NSKeyedArchiver and NSKeyedUnarchiver methods to encode your six instance variables. When it's time to save or load, pack the instance of your class into an NSDictionary (along with a versioning number as I mentioned above) and call NSKeyedArchiver's archiveRootObject:toFile:. Your save an load methods deal only with your own data object, which makes things easy for you. The common pitfall to watch out for here is if your custom data object contains other custom object. This is fine, but you have to make sure every object that's going to be saved has its own NSCoding implementation.
Two things you can do:
Use NSUserDefaults:
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/Reference/Reference.html
The objectForKey method is the one you want to use to store your class. But, as pointed out in the comments, this shouldn't really be used for storing lots of user data; it's best for saving preferences.
For storing more data, you might want to look at Core Data. It's more complex, but should be better suited to your needs. Here's a tutorial on it:
http://mobile.tutsplus.com/tutorials/iphone/iphone-core-data/
Neither of these seems best for your simple application, but I leave this answer up since it gives alternatives for saving data to the iPhone.

writeToFile fails - how do I debug WHY it fails (what tools)?

I'm getting an NSDictionary from JSON (using SBJson), and I want to store it. I'm using
[liveData writeToFile:localFilePath atomically:YES]
and it fails. The data looks like its all NSString, NSDictionary, and NSArray (which "atomically:YES" demands). I used the same localFilePath elesewhere.
So my question is: how can I find out where the problem is? What tools can I use to understand why writeToFile fails? The log doesn't show an error message.
It may have multiple reasons:
The path you are writing to is wrong, not writable (you don't have write access to it), or the parent directory does not exists (if localFilePath is "/path/to/file.plist" but the directory "/path/to/" does not exists, it will fail)
The liveData dictionary does contains objects that are not PropertyList objects. Only NSData, NSDate, NSNumber, NSString, NSArray, or NSDictionary objects can be written into a Property List file (and writeToFile:atomically: do write to a plist file so the dictionary do have to contains only PList objects for that method to succeed)
I know this is a 2 year old question. But since I just had this same problem and fixed it here's what I found. I bet your NSDictionary has some keys that are not NSStrings.
Instead of keying like:
[_myDictionay setObject:thisObj forKey:[NSNumber numberWithInt:keyNumber]];
Key like:
[_myDictionay setObject:thisObj forKey:[NSString stringWithFormat:#"%i",numberWithInt:keyNumber]];
That fixed my problem right up.
The top way can't be saved to a plist file.
Since you're getting your info from a JSON conversion, it is possible that there are some objects or keys that are NSNumbers in there. You would have to convert them. But that's a pain.
So since you already have it in json, just store it as the json string in its entirety in a #"data" key and the re-expand it when you load the plist later back into your array or dict.
I've tried saving an NSDictionary to disk with only numbers for keys and values. Switching the keys to NSString works but not when they keys are NSNumber. Do keys have to be NSString?
EDIT: I know better now that it can be any object that responds to hash; often it's NSString's, though.
Old thread : But this apple thread would be nice to read. Basically iOS has issue in Cache directory. For 1000+ folders it returns error.
I would suggest to add your own atomic mechanism to write file as a fallback.
https://developer.apple.com/forums/thread/128927

OSX: How to store objects in plist file in an OO way

I feel a little dumbfounded. I know how to store any kind of "plist supporting" data in a preferences file, such as NSArray, NSDictionary, NSString and their CF counterparts. No problem there.
Now I like to store the values of my custom object this way. I had thought that if I implement some kind of serialization/archiving protocol, I could get NSUserDefaults to understand my class just like it understand NSDictionary.
E.g, implementing the NSCoding protocol should give the NSUserDefaults code all that it needs: I give it the key names along with the values as plist compatible types (NSString, mostly in my case). But my encoder doesn't even get invoked. :(
Then I thought that there must be at least some function that generates a NSDictionary from the NSCoding protocol, so that I can then send this dict to store in the prefs. Ideally, there'd by something like the NSKeyedArchiver that I pass any NSCoding compatible object and it gives me a NSDictionary, and vice versa. But that doesn't appeat to exist in Apple's framework.
Do I have to write that really myself? I'd expect this would be a quite common need.
Note: I realize that NSKeyedArchiver generates a binary plist, which I could write as a plist file. But that's not what I want. I want to add the contents of this object to my app's prefs plist file, i.e. I want to store both my object and other prefs data in the plist file. That's what doesn't seem to be possible with the given functions.
I'm currently just adding objects to an NSDictionary then calling NSDictionary's "writeToFile:atomically:" method. I'm mostly adding strings, and an image as NSData, but I believe anything I add to the NSDictionary that implements the NSCoding protocol should get written to the file.
Then later when I call NSDictionary's initWithContentsOfFile everything gets put back in the dictionary as it had been. Would this work for you - letting the dictionary take care of the serialization stuff?

Is it possible to store an NSMutableArray together with all its contents into a file and restore it later from there?

Some kind of serialization available in iPhone OS? Is that practically possible or should I quickly forget about that?
I am making a tiny app that stores some inputs in an NSMutableArray. When the user leaves, the inputs should stay alive until he/she returns to continue adding or removing stuff to/from that array.
When the app quits, there must be some way to store all the stuff in the array in a file. Or must I iterate over it, rip everything out and write it i.e. comma-separated somewhere, then the next time go in again, read the stuff in, and iterate over the lines in the file to make an array with that data? That would be hard like a brick. How to?
The easy way, since you already have an NSArray object is to write the array to disk using
- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)flag
and read it back in with:
- (id)initWithContentsOfFile:(NSString *)aPath
or
+ (id)arrayWithContentsOfFile:(NSString *)aPath
You can also use NSCoder.
You can probably search sof for the right code.
So long as the objects in the array implement NSCoding (NSString and NSValue do; if you're storing your own objects it's relatively straightforward), you can use:
[NSKeyedArchiver archiveRootObject: array toFile: filePath];
to save and:
array = [NSKeyedUnarchiver unarchiveObjectWithFile: filePath];
to load.
You can similarly load/save to NSData.
The iPhone SDK is designed to store data using SQLite tables.
You can use NSPropertyListSeralization, since NSArray is a type of property list. You can find more information here.

How to load data from a plist for OpenGL Rendering (iPhone)?

I have an interesting problem.
I have 4 arrays stored in a .plist file, they are called "vertices", "normals", "texCoords" and "polygons" (this file is attached, along with GLViewController.m).
l want to load these arrays into arrays of type Vertex3D, Vector3D, GLfloat and GLubyte respectively, and then render them using OpenGL.
However, I am unsure how load the arrays and was hoping you might be able to help.
Bear in mind that I will want to modify the size of the arrays in the plist, so their size cannot be assumed to be constant (they could have any number of indices).
Links:
Plist: pastie.org/782396
GLViewController.m: pastie.org/782399
Plists are always loaded into arrays or dictionaries of "plist objects": NSData, NSDate, NSNumber, NSString, NSArray, or NSDictionary. So the only way to deal with them is to load the plist into an array or dictionary, then iterate through the resulting objects in order to build new arrays or whatever of the appropriate type.
So basically you'll need to write some sort of code to "translate" from plist to the object types needed by OpenGL.
Check out NSArray arrayWithContentsOfFile: and NSDictionary dictionaryWithContentsOfFile:
Also see the Property List Programming Guide.