I have an app that allows the user to build a simple playlist which is stored as an array of MPMediaItems. When the app quits or enters the background, I want to store the playlist in a file and retrieve it when the user opens the app again.
Should I just be saving an id in a file as opposed to a whole MPMediaItem object?
Also, as the user's library may have changed how would I compare the saved list against the iPod library, do I loop through and run a bunch of queries?
Save this array into plist file, which is a effective way to save and read from local file.
Here in below are metheds to create, save, read data from plist. Hope it is helpful for you.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *doc = [paths objectAtIndex:0]; //path of document folder
NSString *path = [doc stringByAppendingPathComponent:#"nameOfPlist.plist"]; //get the path of your plist in document folder.
NSDictionary* dic = [NSDictionary dictionaryWithObjectsAndKeys:#"123456",#"number", nil]; //save your data into a dictionary or array.
[dic writeToFile:path atomically:YES]; //then write the dic/array into the plist file.
NSDictionary* dic2 = [NSDictionary dictionaryWithContentsOfFile:path]; //read data from plist.
NSLog(#"dic2 is:%#",[dic2 objectForKey:#"number"]);
Related
even after so many research i haven't found a solution for this question. I am currently working on a app which uses 3 view controllers for Registration with a log out button. the last view controller has the Register button which saves all the details of registration in a web service. But if the user has filled the two view forms and logs out. The two view filled forms field should be saved in the local memory and wen the user logs it again the pre filled forms should load the fields saved in internal memory just to continue the Registration for webservice. Any idea how to implement this sort of functionality
As others have said, NSUserDefaults will suffice for what you need.
NSUserDefaults *registrationInfo = [NSUserDefaults standardUserDefaults];
Guessing you have text fields with the info you need. So pull out the text and save to a key like this.
[registrationInfo setObject:self.someTextFieldName.text forKey#"firstTextField"];
After repeating this for every text field(use different key names though), call this [registrationInfo synchronize];
To pull the data out, you open the defaults again just like the first line. And to retrieve a specific key: NSString *firstTextField = [registrationInfo objectForKey:#"firstTextField"];
To make this easier, you can also put all of your strings in an array or dictionary, and then add that as an object in your defaults. Then you only have to set/get once.
If you have large amount of data to save use CoreData else you NSUserDefaults to save it.
I suggest you to use PLIST There are mainly three steps to do this.
1) Generate .plist file.
NSError *error1;
BOOL resourcesAlreadyInDocumentsDirectory;
BOOL copied1;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath1 = [documentsDirectory stringByAppendingString:#"/epub.plist"];
resourcesAlreadyInDocumentsDirectory = [fileManager fileExistsAtPath:filePath1];
if(resourcesAlreadyInDocumentsDirectory == YES) {
} else {
NSString *path1 = [[[NSBundle mainBundle] resourcePath] stringByAppendingFormat:#"/epub.plist"];
copied1 = [fileManager copyItemAtPath:path1 toPath:filePath1 error:&error1];
if (!copied1) {
NSAssert1(0, #"Failed to copy epub.plist. Error %#", [error1 localizedDescription]);
}
}
2) Try to read(open) it.
NSMutableDictionary* dict = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath1];
3) write data to plist file.
[dict setObject:[NSNumber numberWithInt:value] forKey:#"value"];
[dict writeToFile:path atomically:YES];
This is a simple way to use it. I suggest to use .plist file in place of NSUserDefaults.
How can I append values to an existing key in NSDictionary from a plist?
What I have is basically a plist saved in disc with a few keys and values, the keys are the names of some students with one initial value. What I’m trying to do that doesn't work is to append more items to existing keys/Students by reading the plist, adding it to a temporary NSDictionary, appending a temporary array to an existing key in the plist but when I save the plist back it doesn’t work, it only saves the last two items and basically deletes the initial value for that key.
Here is the code that I’m using…
- (IBAction)testing:(id)sender
{
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [dirPaths objectAtIndex:0];
NSString *fullPath = [documentsPath stringByAppendingPathComponent:#"studentsRecords.plist"];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:fullPath];
if(fileExists)
{
NSMutableDictionary *dictionaryRecords = [[NSMutableDictionary alloc]initWithContentsOfFile:fullPath];
NSLog(#"Items for Nathan: %#",[dictionaryRecords objectForKey:#"Nathan"]);// here the output is, Items for Nathan: Ruler
// which make sense since I only had one initial record for Nathan in my plist,
// Here, I want to add two more items to the key Nathan by appending an arry to
// NSMutableDictionary (dictionaryRecords) but it doesnt work
NSArray *tempArray = #[#"NoteBook", #"Pencil"];
[dictionaryRecords setObject:tempArray forKey:#"Nathan"];
[dictionaryRecords writeToFile:fullPath atomically:YES];
// when I check the plist after saving this, I only see the last two values, NoteBook and Pencil
// instead of the three that I'm expecting, Ruler, NoteBook and Pencil
}
}
What am I missing here?
Thanks a lot in advance.
[dictionaryRecords setObject:tempArray forKey:#"Nathan"] replaces whatever the previous value was with tempArray.
If you want to add to the existing array, you have to retrieve it, make a mutable copy, and append to it.
Here is how I made it work. I hope I didn't over complicated things here but for some reason I had to use two arrays, an NSArray and an NSMutableArray, I would think that the NSMutableArray would be enough but it didn't work.
- (IBAction)testing:(id)sender
{
// get directory path
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [dirPaths objectAtIndex:0];
// create plist
NSString *fullPath = [documentsPath stringByAppendingPathComponent:#"studentsRecords.plist"];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:fullPath];
// if file exists create dictionary
if(fileExists)
{
// add items from plist to dictionary
NSDictionary *dictionaryExistingRecords = [[NSDictionary alloc]initWithContentsOfFile:fullPath];
// make a copy if dictinary with existing items
NSMutableDictionary *dictionaryNewRecords = [dictionaryExistingRecords mutableCopy];
// array to hold existing values from a spcecified key
NSArray *arrayWithExistingKey = [dictionaryExistingRecords objectForKey:#"Nathan"];
// mutable array to add existing and be able to insert new items
NSMutableArray *arrayOldAndNewItems = [NSMutableArray arrayWithArray:arrayWithExistingKey];
// insert new items to array
[arrayOldAndNewItems addObject:#"Snow Pans"];
// add old and new items to specified key
[dictionaryNewRecords setObject:arrayOldAndNewItems forKey:#"Nathan"];
// save new records to plist
[dictionaryNewRecords writeToFile:fullPath atomically:YES];
}
}
#end
What I've known:
How make requests to server for uploading I will use AFNetworking
How access photos and videos with help of ALAssetsLibrary
I think I must use CoreData to keep info about:last syncing, photos already uploaded, etc. I worked already with coreData it will no be a problem.
My problems are logic, flow how can achieve this auto back up and of course to be optimum(minimum requests, short way). What steps must follow to achieve this scope?
Any thoughts?
I think CoreData is too heavy in this situation. You may want to use plist to store your info data .here are some steps to follow .
After loading image from server, create a dictionary to store the message you want and create another dictionary to store these messages , and use image's url as the key of this dictionary. It might look like this:
imageUrl = {
lastSyncTime = xxxxxxxxxx,
photoUploaded = 0,
}
Create a plist file to save this dictionary:
- (NSString *)filePath:(NSString *) fileName{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
return [documentsDirectory stringByAppendingPathComponent:fileName];
}
[yourImageDictionary writeToFile:[self filePath:#"imageInfo.plist"] atomically:YES];
Read or write your plist file anytime you want:
if ([[NSFileManager defaultManager] fileExistsAtPath:[self filePath:#"imageInfo.plist"]]) {
NSDictionary *imageInfo = [NSDictionary dictionaryWithContentsOfFile:[self filePath:#"imageInfo.plist"]];
}
How to update the existing plist with info? I have simple dictionary with strings. Here is my save method:
#define DOCUMENTS [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]
- (IBAction)saveData:(id)sender {
NSMutableDictionary *data = [NSMutableDictionarydictionaryWithObjects:#[self.textFieldOne.text, self.textFieldTwo.text, self.textFieldThree.text] forKeys:#[#"Key1", #"Key2", #"Key3"]];
NSError *error = nil;
NSData *dataToPlist = [NSPropertyListSerialization dataWithPropertyList:data format:NSPropertyListXMLFormat_v1_0 options:0 error:&error];
NSString *path = [DOCUMENTS stringByAppendingPathComponent:#"userData.plist"];
[dataToPlist writeToFile:path atomically:YES];
}
So, it's OK when I call this method from Class 1, but when I want to update this plist with other info from Class 2 – it overwrites old info with new info. What I should do to update the existing plist with new info from other classes?
You need to load the existing plist into an NSDictionary or NSArray (as appropriate), then update the data with the additional data, and finally write out the updated data to the plist file.
Basically the existing one you have to read into dictionary using dictionarywithcontentsfile method and then on the basis of your requirement use setobjecwt method into dictionary and then write to plist. So that old value will be retain there and you can updates new as well.
My app is a list of items that the user can rate and take notes on etc. All of these items (dictionaries that store the user ratings and notes) are stored in a plist which is moved to the documents directory when the app first loads (if the plist file already exists in documents directory it skips this step). Now I've had a few reviews and people have been saying there should be more items in the lists. Now I'm trying to figure out how to go about adding new items to the plist. If I add them to the existing plist the users will never see the new items because the app checks to see if the database already exists in the documents directory. So they will never receive the new list. So I planned on creating a new plist with items in it and appending each new item to the old plist if the item doesn't already exist (because the user can add items themselves so I don't want to have duplicate entries in case the user added an item with the same name). My dilemma is I'm not sure where exactly/how to do the plist merging. Do I do it in the App Delegate? Do I do it in the viewDidLoad of the main view? How do I stop it from checking every time the app loads if it has already added the new items to the old plist? I know there are different ways to do it. I'm just looking for the easiest and "less load heavy on the app" way of doing it.
Ok. I solved it thanks to a couple people in one of the iOS chats. So basically inside the application didFinishLaunchingWithOptions method in my AppDelegate.m I loaded both plists into 2 different NSArrays array1 and array2, I also created an NSMutableArray array3 which I loaded with the original plist that was in the users documents directory.Then I looped through them both checking to make sure I didn't add any duplicate items based on their Name_Key (because the items in the arrays are dictionaries). If the items didn't match then I would add them to the 3rd array (array3). Then I saved array3 out to the original plist file path. Then I set an integer inside the user defaults so It would only perform this task once. I didn't want the app to go through this EVERY time the user opened the app. Below is the code I used.
int haveMergedPlist = [[NSUserDefaults standardUserDefaults] integerForKey:#"merged plist"];
if (haveMergedPlist < 1){
// I used a integer rather than a BOOL because if I ever want to perform this operation again with another app update all I have to do is change the number.
// merge code here
//new plist
NSString *newPlistPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"NewPlist.plist"];
NSArray *newPlistArray = [[NSArray alloc]initWithContentsOfFile:newPlistPath];
//original plist in user documents directory
NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [searchPaths lastObject];
NSString *originalPlistPath = [documentsDirectory stringByAppendingPathComponent:#"originalPlist.plist"];
NSArray *originalPlistArray = [[NSMutableArray alloc]initWithContentsOfFile:originalPlistPath];
NSMutableArray *combinedPlistArray = [[NSMutableArray alloc]initWithContentsOfFile:originalPlistPath];
// Loop through both plists arrays and add if it does not match/exist.
BOOL itemExists = YES;
for (NSDictionary *newItem in newPlistArray) {
for (NSDictionary *originalItem in originalPlistArray) {
NSString * newItemNameString = [[newItem objectForKey:NAME_KEY] lowercaseString];
NSString * origItemNameString = [[originalItem objectForKey:NAME_KEY] lowercaseString];
//Compare lowercase strings and if they don't match then add them to the original plist array.
if ([newItemNameString isEqualToString:origItemNameString]) {
itemExists = YES;
break;
} else {
itemExists = NO;
//doesn't match so add it
}
}
if (itemExists == NO) {
[combinedPlistArray addObject:newItem];
NSLog(#"newItem added");
itemExists = YES;
}
}
//Write Array With New Items Added to documents directory
NSString *writeableDBPath = [documentsDirectory stringByAppendingPathComponent:#"originalPlist.plist"];
[combinedPlistArray writeToFile:writeableDBPath atomically:YES];
//set integer to 1 in user defaults so it only merge's once
//I comment this out while getting the loops to work otherwise you will have to delete the app out of the simulator or the phone to make sure its working every time.
[[NSUserDefaults standardUserDefaults] setInteger:1 forKey:#"merged plist"];
}