So in my last question I tried to figure out what should I use, Plist or Core data or sqlight and I've decided that I'll try all of them to improve my skills.
So I've started reading about plist and the way they work and i'm not really sure about a few things. The app purpose I'm writing is to give the user a few lists of different songs from different genre from plist files that looks like this:
The user will be abale to choose what songs he likes and those will be added to a new list.
Can I copy songs (a simple Dictionary in a plist file in my case) and create a new plist out of them. Or should I use a stack or an array to push the songs in and use a table view as an outlet? Eventually I want the user to have saved playlists he created.
I'm curious to know if something that I've suggested won't work and what is a more elegant approach for doing so.
Thanks
Try it like this,
NSString *plistFileName = [[self documentPath] stringByAppendingPathComponent: #"Original.plist"];
if ([[NSFileManager defaultManager] fileExistsAtPath:plistFileName]) {
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:plistFileName];
}
Show this data in table view and ask the user to select the songs. Save the selected one in another dictionary as,
NSDictionary *savedPlayListDict = //saved songs
NSString *fileName = [[self documentPath] stringByAppendingPathComponent: #"SavedList.plist"];
[savedPlayListDict writeToFile: fileName atomically:YES];
Or you can create your own model classes for saving the key value pairs in dictionary and use that to represent each row of the table.
For eg:- Song can be a model object with properties as, UIImage *pic, NSInteger number and NSString *name. You can add these Song objects in an array and populate your table view, using this array. Once user has selected the list, you can convert the saved list into a dictionary and save to plist as shown above.
These are just a few options. You can do it a lot of different ways.
Related
I am working on an app that display photos of buildings along with some information about them. The photos are jpegs that all come in the app bundle, and the Building objects associated with them have a few properties such as name, address, and of course, a photos array. I'm loading the Building objects from a plist when the app launches. Everything's pretty straight forward, except that when the user scrolls through the images of buildings they have the option to add the ones they like to a favourite's list for viewing later.
Originally I was going to save each Building object they favorited using Core Data, but now that I think about it it seems a little redundant because all of the Building objects are already loaded from the plist. When the user is scrolling through the images of each building the photos have to display an indication of weather that building has been added to the favourite's list yet, which means I'll have to continuously compare an array of objects taken from CoreData with an array of objects loaded from a plist, which seems like it could be a memory wasting task.
I was wondering if, as an alternative to CoreData, I could add a unique ID property to the Building object and store it in the plist with them. Then when the user adds a Building to their favourites list I can just add it's UID to an array in NSUSerDefaults and make the comparison that way. Does that seem like a sensible way to tackle this?
Storing data like this in NSUserDefaults is a really bad habit to get into. Save user preferences in NSUserDefaults, not sets of data.
Much better idea is to save the user's favorites in a file in the Documents folder. If you've added an "ID property" to your Building object, you can maintain an array of selected IDs. That array can be saved to and read from disk with:
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [documentPaths objectAtIndex:0];
NSString *myFile = [documentsDirectory stringByAppendingPathComponent:#"myFavs"];
and then
// save the array contents to file named "myFavs"
[a writeToFile:myFile atomically:YES];
or
// read the saved array when you launch the app
NSArray *b = [NSArray arrayWithContentsOfFile:myFile];
Of course, you'll want to add error handling, but this is a much, much better idea than stuffing an array into NSUserDefaults.
Perhaps using CoreData for favourites is OK, although, consider using Sets which stores distinct values of the same type in a collection with no defined ordering
Assumptions:
- Your buildings data isn't coming from a dynamic/external source
- You don't have a massive amount of data.
why not add a property to the buildings to flag it as a favorite and store that local when the app goes to the background. (NSUserDefaults or document directory as plist)?. Then in future app loads use the local one that has the flags.
That way you don't need an additional data structure to store identifiers and a list of favorites.
CoreData seems like overkill for the problem you're describing.
I know this question had been asked for several times, but I have trouble reading data in Xcode iOS. The problem was to achieve an implementation without having the keys for NSDictionaries hardcoded in the code.
Let's say, we have this .plist:
This is my plist
In this case I want to access the name and address from the restaurants dynamically without accessing the data by a hardcoded string.
Background of this is that I try to access the data on every cell on a grouped UITableView for iOS.
Anyone has some good information about this?
Generally (normally I code in c#) I know how to access dictionaries. But in this case, there are nested dictionaries with arrays which get me really confused and also frustrating :(
NSString *path = [[NSBundle mainBundle] pathForResource:#"PropertyListName" ofType:#"plist"];
//Plist should exist in main bundle
NSDictionary *root = [[NSDictionary alloc] initWithContentsOfFile:path];
Then in your case your first value is a array in dictionary read that object in an array like,
NSArray * restaurantsArray = [names objectForKey:#"restaurants"];
Then so forth You know what type of object exist in the hierarchy just call respective methods of each,
like objectForKey for dictionary.
objectAtIndex for array.
I am learning Objective-C language. I have covered the following questions:
What is plist?
How to create a plist file?
What are the representation of plist file?
But I did not find the answer of these questions:
Why do we store a plist in NSArray?
What is the need to store a plist into NSArray?
Can you please help me to clear my doubts?
Sometime you want to do something at runtime or create something base on something else.
Let's imagine you have a game with a different levels and you want the levels to be vary you can hard code the levels in code but much nicer would be store it in the file. iOS lets you very easily load plist to array or dictionary and that's the reason why iOS developers choose to use it.
// Example of plist file
Level1:
NumberOfEnemies: 6
ScoreTarget: 100
....
Level2:
NumberOfEnemies: 12
ScoreTarget: 120
....
When you load the game you can read the plist and you can load the level base on the content.
It's much easier to add another level or add more customisation to the plist (file) that go back to the code any do it there.
It's just one of the examples but you could use plist to do much more.
Plist are mostly configuration files or place to store some values that you know that will never change. One particular example of the plist file is info.plist where you define attributes for the application.
Plist are nothing else but the same old XML file with attributes and elements. That said, you actually access plist through dictionary, not array.
For your question why do we store it in dictionary, you use dictionary to access these values since there is no other way to extract the information from it.
One more thing, plists have their own restrictions regarding the type you can store: Array, Dictionary, String, Date, Data, Number and Boolean.
PList : is a "Property List" file, uses the XML format to store objects such as arrays, dictionaries, String, Data, Number and Boolean.
How to create :
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:#"myPlistFile.plist"];
if (![fileManager fileExistsAtPath: path])
{
NSString *bundle = [[NSBundle mainBundle] pathForResource:#”myPlistFile” ofType:#”plist”];
[fileManager copyItemAtPath:bundle toPath:path error:&error];
}
[myDict writeToFile:plistPath atomically: YES];
Representation : Based on what is stored in plist file .
Key and Value. (NSDictionaries)
Key and multiple value . (NSArray) etc..
What is PLIST?
Plist stands for Property List. Plist is used to store data in hierarchical manner.A Property List can contain containers and primitives.
Containers – Array, Dictionary
Primitives – Boolean, String, Number(Integer,Float), Date, Data
A Container can contain other containers and primitive data-types.
i.e. Dictionary can contain other Dictionaries,Arrays and Primitives. Array can contain other Dictionaries,Arrays,Primitives.
How to Create PLIST File?
STEP 1: Right Click the Project
STEP 2: Choose New File
STEP 3: Select Resource from left side of the Template.
STEP 4: Then Click Property List
STEP 5: Click NEXT button of the Bottom.
STEP 6: Give property List Name.
STEP 7: Finally Click OK
For more Reference please go through the below link
https://stackoverflow.com/questions/9044735/steps-to-create-and-edit-a-plist-file-in-xcode
What are the Representation of PLIST file?
A property list can be stored in one of three different ways:
1. in an XML representation,
2. in a binary format, or
3. in an “old-style” ASCII format inherited from OpenStep.
You can serialize property lists in the XML and binary formats. The serialization API with the old-style format is read-only
XML property lists are more portable than the binary alternative and can be manually edited, but binary property lists are much more compact; as a result, they require less memory and can be read and written much faster than XML property lists. In general, if your property list is relatively small, the benefits of XML property lists outweigh the I/O speed and compactness that comes with binary property lists. If you have a large data set, binary property lists, keyed archives, or custom data formats are a better solution.
I refer the link for Why do we store a plist in NSArray? and What is the need to store a plist into NSArray?
1.http://hayageek.com/plist-tutorial/
2.https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/PropertyLists/AboutPropertyLists/AboutPropertyLists.html
3.http://nscookbook.com/2013/02/ios-programming-recipe-13-using-property-lists-plists/
4.Getting plist data in a order
Is it possible to export data to a Xcode-project file?
For example, I want to generate a new "hello.csv" file, using swift, that says "hello world"
into my Xcode Project locally but not in in-app document.
To put it simply, no. If you want to use databases in code, use .plist (Preference List) files. Unfortunately, I don't know how to do this in Swift, but I do know how to in Objective-C.
To start off, make a PLIST file in Xcode, and add your data to it. Remember the key name values.
In your .m file, add this code to create an NSMutableDictionary that you can modify in code later:
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"yourFile" ofType:#"plist"]];
Then, to pull data out of the dictionary you made (dict), do something like this. Switch data types as necessary.
NSString *helloWorld = (NSString*)[dict valueForKey:#"yourKeyName"];
(Note: the cast of NSString* is necessary because, otherwise, it will yell at you for having the incompatible type of id. In Swift, it's object. If you plan on modifying the string, then use NSMutableString.)
Then, to save it to the file, save the key/value pair in the dictionary:
[dict setValue:helloWorld forKey:#"yourKeyName"];
And finally, save the dictionary and overwrite the PLIST file.
[dict writeToFile:[[NSBundle mainBundle] pathForResource:#"yourFile" ofType:#"plist"] atomically:YES];
Note: the writeToFile method's atomically parameter is asking whether or not it has to write the file right away or after it does whatever it needs to (as in, it's not a high priority). I recommend setting this to YES or true.
I am very confused on how to use NSMutableArrays to store multiple dimensions of data.
I'm trying to store a car's make, model, year, and a description of a car (which is an NSString) in an array. The app plays a sound, loads the description, and shows a picture of the car. Originally, I was using a PLIST file to store this information. This was then loaded into a dictionary as the view loaded. However, I am no longer implementing the PLIST file, since it would be much easier for the program to automatically generate this data at runtime, based on the folders in the project.
The folders are broken down as follows:
(Main Resources Folder) -> Makes -> Models -> Years -> Folder containing picture, .mp3, and file with description
For example:
Cars -> Ford -> Mustang -> 1965 -> Pic, .mp3, description in file
//Go to folder
NSString * resourcePath = [[NSBundle mainBundle] resourcePath];
NSString * documentsPath = [resourcePath stringByAppendingPathComponent:#"Cars"];
NSError *error;
//Load names of all makes in folder into memory
NSArray * listOfMakes = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsPath error:&error];
I then use multiple 'for' loops to iterate through this and all other folders, and to load everything else in to NSArrays.
However, I need one single array that is accessible program-wide. So, I am doing this within a singleton. I would like to add these arrays to an NSMutableArray, so that I can access it anywhere. I have viewed many other questions, like these:
objective-c accessing arrays, Adding objects in Multidimensional NSMutableArray, How to add string objects to NSMutableArray, But am still very confused since these only cover up to three dimensions. Having multiple arrays of arrays is very confusing...
Any help would be very much appreciated.
when it comes to multi-dimension...
I suggest you to use NSMutableDictionary or NSDictionary.
But the worst thing I see in your implementation is you are trying to load/hold the whole app data at once, Which will remain in memory till the app is not quit, since its store in singleton.
It will be better if you use CoreData and load only content which is required.
I don't know how you are building your app's logic, but if I were you, I would do something like this:
1. Make navigation based app.
2. In the first view show the list of models (load the list of models from Makes folder).
3. When particular model is selected, in the next view show the list of years.
etc.
And, no need to read all the contents of all folders in to the array. Good Luck!
If you want a 2 dimensional array, than just one car array to it for each car:
[2dimArray addObject:#[make, model, year, description]];