Load playlist with MPMediaQuery - ios

in my app I want to save user playlist in a plist file and load this playlist when app start.
this is the code that I use to save:
if (self.backgroundMusicItems) {
NSMutableArray *songsID = [[NSMutableArray alloc] initWithCapacity:0];
MPMediaItem *item;
for (item in self.backgroundMusicItems.items) {
NSNumber *songId = [item valueForProperty:MPMediaItemPropertyPersistentID];
[songsID addObject:songId];
}
NSString *documentdir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *filePath = [documentdir stringByAppendingPathComponent:#"playlist.plist"];
[songsID writeToFile:filePath atomically:YES];
}
and this is the code that I use to load:
NSString *documentdir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *filePath = [documentdir stringByAppendingPathComponent:#"playlist.plist"];
NSArray *myArray = [[NSArray alloc] initWithContentsOfFile:filePath];
NSMutableSet *predicates = [[NSMutableSet alloc] initWithCapacity:0];
if (myArray.count > 0) {
NSNumber *songId;
for (songId in myArray) {
MPMediaPropertyPredicate *predicate = [MPMediaPropertyPredicate predicateWithValue:songId forProperty:MPMediaItemPropertyPersistentID];
[predicates addObject:predicate];
}
MPMediaQuery *query = [[MPMediaQuery alloc] initWithFilterPredicates:predicates];
NSArray *mediaItems = [query items];
if (mediaItems.count > 0) [GameOptions sharedClass].backgroundMusicItems = [[MPMediaItemCollection alloc] initWithItems:mediaItems];
}
myArray contains 2 items but [query items] method return 0 items. Where I'm wrong??

You're asking for songs where MPMediaItemPropertyPersistentID is set to the value for song1 AND song2 - which will always return zero results as it's logically impossible for any songs to match two different MPMediaItemPropertyPersistentIDs.
You need to run a query for each persistent id.

Related

Write NSArray to plist file

I have a code to get the data of a plist file and a code to write data to a plist file. Now the things is, that it add's the readed data in one array (See images).
I want it in different arrays (See green image)
HERE IS MY CODE:
- (void)WriteData {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"MuziekList.plist"];
if ([fileManager fileExistsAtPath:path] == NO) {
NSString *resourcePath = [[NSBundle mainBundle] pathForResource:#"MuziekList" ofType:#"plist"];
[fileManager copyItemAtPath:resourcePath toPath:path error:&error];
}
//_______________________________________________________________________________________________________________
NSMutableDictionary *savedStock = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
//load from savedStock example int value
NSArray *NummerTexts;
NummerTexts = [savedStock objectForKey:#"Nummers"];
NSString *NummerTextsR = [[NummerTexts valueForKey:#"description"] componentsJoinedByString:#" - "];
NSArray *ArtiestTexts;
ArtiestTexts = [savedStock objectForKey:#"Artiesten"];
NSString *ArtiestTextsR = [[ArtiestTexts valueForKey:#"description"] componentsJoinedByString:#" - "];
//_______________________________________________________________________________________________________________
NSUserDefaults *CurrentVideoNummerResult = [NSUserDefaults standardUserDefaults];
NSString *CurrentVideoNummer = [CurrentVideoNummerResult stringForKey:#"CurrentVideoNummer"];
NSUserDefaults *CurrentVideoArtiestResult = [NSUserDefaults standardUserDefaults];
NSString *CurrentVideoArtiest = [CurrentVideoArtiestResult stringForKey:#"CurrentVideoArtiest"];
/*
NSUserDefaults *CurrentVideoIDResult = [NSUserDefaults standardUserDefaults];
NSString *CurrentVideoID = [CurrentVideoIDResult stringForKey:#"CurrentVideoID"];
*/
NSMutableDictionary *plist = [[NSDictionary dictionaryWithContentsOfFile:path] mutableCopy];
NSMutableArray *newArray = [[NSMutableArray alloc] init];
NSMutableArray *newArray2 = [[NSMutableArray alloc] init];
newArray = [NSMutableArray arrayWithObjects:CurrentVideoNummer, NummerTextsR, nil];
[plist setObject:newArray forKey:#"Nummers"];
newArray2 = [NSMutableArray arrayWithObjects:CurrentVideoArtiest, ArtiestTextsR, nil];
[plist setObject:newArray2 forKey:#"Artiesten"];
[plist writeToFile:path atomically:YES];
}
Click link for images
https://www.dropbox.com/sh/wrk8h8cnwye8myx/AADl4omkGdl3S4ESXv6NbymVa?dl=0
Your question and problem are confusing. Maybe this will help:
Your code reads your current array (NummerTexts), flattens that array to a single string (NummerTextsR), gets a second string (CurrentVideoNummer), then builds a two-element array (newArray).
Your question appears to be why do you get a two-element array...?
If you don't want to flatten your original array don't do so, just make a mutable copy of it, something like:
NSMutableArray *existingTexts = [[NummerTexts valueForKey:#"description"] mutableCopy];
add your new element:
[existingTexts addObject:currentVideoNummer];
and write it back like you already are.
HTH
BTW Do not start local variable names with an uppercase letter, this goes against convention and is why the syntax highlighting in your question is all wrong.

Sort array with dictionaries by date

I have an NSArray with NSDictionary inside. It looks like:
etc.
I need to sort it by date inside NSDictionary. I need something like this:
How can I do this? Here is my method which gives me first unsorted array:
- (void)iterateOverDocumentsDirectory
{
arrayWithFiles = [NSMutableArray new];
NSFileManager *fileManager = [[NSFileManager alloc] init];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirPath = [paths objectAtIndex:0];
NSString *finalPathToFolder = [NSString stringWithFormat:#"%#/", documentsDirPath];
albumNames = [[fileManager contentsOfDirectoryAtPath:finalPathToFolder error:&error] mutableCopy];
if (albumNames == nil) {
// error...
}
for (NSString *album in albumNames)
{
NSMutableDictionary *tempDict = [[NSMutableDictionary alloc] init];
[tempDict setValue:album forKey:#"name"];
NSString *finalPathToFiles = [NSString stringWithFormat:#"%#/%#", documentsDirPath, album];
NSArray *tempArray = [fileManager contentsOfDirectoryAtPath:finalPathToFiles error:&error];
NSMutableArray *arrayWithEachFiles = [NSMutableArray new];
for (NSString *tempString in tempArray)
{
NSMutableDictionary *eachFileDict = [[NSMutableDictionary alloc] init];
NSString *pathToFile = [NSString stringWithFormat:#"%#/%#/%#", documentsDirPath, album, tempString];
[eachFileDict setValue:pathToFile forKey:#"path"];
NSDictionary *filePathsArray1 = [[NSFileManager defaultManager] attributesOfItemAtPath:pathToFile error:nil];
NSDate *modifiedDate = [filePathsArray1 objectForKey:NSFileCreationDate];
[eachFileDict setValue:modifiedDate forKey:#"date"];
[arrayWithEachFiles addObject:eachFileDict];
}
NSSortDescriptor *ageDescriptor = [[NSSortDescriptor alloc] initWithKey:#"date" ascending:YES];
NSArray *sortDescriptors = #[ageDescriptor];
NSArray *sortedArrayWithFiles = [[arrayWithEachFiles sortedArrayUsingDescriptors:sortDescriptors] mutableCopy];
[tempDict setValue:sortedArrayWithFiles forKey:#"files"];
[arrayWithFiles addObject:tempDict];
}
}
Use following code for sorting the array of dictionaries:
NSArray * sortedArray = [myArray sortedArrayUsingComparator:^(id obj1, id obj2) {
NSNumber *rating1 = [(NSDictionary *)obj1 objectForKey:#"date"];
NSNumber *rating2 = [(NSDictionary *)obj2 objectForKey:#"date"];
return [rating1 compare:rating2];
}];
You can sort it easily by using sortArrayUsingComparator:
[array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return //pseudo-code: {obj1->dict->date isLaterThan obj2->dict->date};
}];
I sort it. Not sure that my code is clear and well optimized. But here is a solution:
NSMutableArray *masterArray = [NSMutableArray new];
NSMutableArray *sameDates = [NSMutableArray new];
BOOL started = NO;
NSString *prevDate;
for (NSDictionary *dict in sortedArrayWithFiles)
{
NSString *tempString = [dict objectForKey:#"date"];
if (started)
{
if ([tempString isEqualToString:prevDate])
{
[sameDates addObject:dict];
}
else
{
NSMutableDictionary *tempDict = [[NSMutableDictionary alloc] init];
[tempDict setValue:tempString forKey:tempString];
[tempDict setValue:sameDates forKey:#"files"];
[masterArray addObject:tempDict];
prevDate = tempString;
[sameDates removeAllObjects];
[sameDates addObject:tempString];
}
}
else
{
// first element
started = YES;
prevDate = tempString;
[sameDates addObject:dict];
}
}
// last value
NSMutableDictionary *tempDict = [[NSMutableDictionary alloc] init];
[tempDict setValue:prevDate forKey:prevDate];
[tempDict setValue:sameDates forKey:#"files"];
[masterArray addObject:tempDict];
In master array we store array with dictionaries separated by date.

Archiving data and then loading it on viewdidload

Im following an Objective-C tutorial and on this task I have to make an address book style app that stores contact details after pressing a button and then on the next load restores them.
Having problems figuring out why text doesn't appear to be being saved - so will obviously not load next time I load the app in the simulator.
[super viewDidLoad];
NSFileManager *filemgr;
NSString *documentsDirectory;
NSArray *directoryPaths;
filemgr =[NSFileManager defaultManager];
directoryPaths = NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES);
documentsDirectory =[directoryPaths objectAtIndex:0];
filePath =[[NSString alloc]initWithString:[documentsDirectory stringByAppendingPathComponent:#"userInfo.dat"]];
if ([filemgr fileExistsAtPath:filePath])
{
NSMutableArray *userData;
userData =[NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
txtFirstName.text =[userData objectAtIndex:0];
txtLastName.text =[userData objectAtIndex:1];
txtEmail.text =[userData objectAtIndex:2];
txtPhone.text =[userData objectAtIndex:3];
NSLog(#"File Has Been loaded");
}else
{
NSLog(#"Error.");
}
}
- (IBAction)btnSaveDetails:(id)sender {
NSMutableArray *contactDetails;
contactDetails =[[NSMutableArray alloc]init];
[contactDetails addObject:txtFirstName.text];
[contactDetails addObject:txtLastName.text];
[contactDetails addObject:txtEmail.text];
[contactDetails addObject:txtPhone.text];
[NSKeyedArchiver archiveRootObject:contactDetails toFile:filePath];
NSLog(#"File Saved");
}
Thanks in advance
Have you tried this?
-(id)viewDidLoad
{
NSMutableArray * userData = [[NSMutableArray alloc] init];
NSData * downloadedData = [[NSData alloc] initWithContentsOfFile: [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/userInfo.plist"]];
if (downloadedData.length)
[userData setArray:[NSKeyedUnarchiver unarchiveObjectWithData:downloadedData]];
NSLog(#"userData :%#", userData);
downloadedData = nil;
}
-(IBAction)btnSaveDetails:(id)sender
{
NSMutableArray * contactDetails =[[NSMutableArray alloc]init];
[contactDetails addObject:txtFirstName.text];
[contactDetails addObject:txtLastName.text];
[contactDetails addObject:txtEmail.text];
[contactDetails addObject:txtPhone.text];
NSData * contactData = [NSKeyedArchiver archivedDataWithRootObject:contactDetails];
[contactData writeToFile:[NSHomeDirectory() stringByAppendingPathComponent:#"Documents/userInfo.plist"] atomically:YES];
contactData = nil;
}

How to stop overwriting data

I am trying to save in my iOS app some data. I use the following code :
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"yourPlist.plist"];
//inserting data
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setValue:categoryField.text forKey:#"Category"];
[dict setValue:nameField.text forKey:#"Name"];
[dict setValue:eventField.text forKey:#"Event"];
NSMutableArray *arr = [[NSMutableArray alloc] init];
[arr addObject:dict];
[arr writeToFile: path atomically:YES];
//retrieving data
NSMutableArray *savedStock = [[NSMutableArray alloc] initWithContentsOfFile: path];
for (NSDictionary *dict in savedStock) {
NSLog(#"my Note : %#",dict);
}
However the NSLog shows me only the last data... I suppose that i am overwriting here..I cant see why though!
How can i continue to save dictionaries in the array without overwriting? Any ideas?
Since you are making a model object it would be better if you include save, remove, findAll, findByUniqueId kind of logic built into it. Will make working with the model object very simple.
#interface Note : NSObject
#property (nonatomic, copy) NSString *category;
#property (nonatomic, copy) NSString *name;
#property (nonatomic, copy) NSString *event;
- (id)initWithDictionary:(NSDictionary *)dictionary;
/*Find all saved notes*/
+ (NSArray *)savedNotes;
/*Saved current note*/
- (void)save;
/*Removes note from plist*/
- (void)remove;
Save a note
Note *note = [Note new];
note.category = ...
note.name = ...
note.event = ...
[note save];
Delete from saved list
//Find the reference to the note you want to delete
Note *note = self.savedNotes[index];
[note remove];
Find all saved notes
NSArray *savedNotes = [Note savedNotes];
Source Code
Replace:
NSMutableArray *arr = [[NSMutableArray alloc] init];
[arr addObject:dict];
[arr writeToFile: path atomically:YES];
With:
NSMutableArray *arr = [[NSMutableArray alloc] initWithContentsOfFile: path];
[arr addObject:dict];
[arr writeToFile: path atomically:YES];
You need to first read in the data, then APPEND the new dictionary to the old one. So read the file first, then append the new dictionary, then save.
FULL CODE:
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setValue:categoryField.text forKey:#"Category"];
[dict setValue:nameField.text forKey:#"Name"];
[dict setValue:eventField.text forKey:#"Event"];
[self writeDictionary:dict];
- (void)writeDictionary:(NSDictionary *)dict
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"yourPlist.plist"];
NSMutableArray *savedStock = [[NSMutableArray alloc] initWithContentsOfFile: path];
if(!savedStock) {
savedStock = [[[NSMutableArray alloc] initiWithCapacity:1];
}
[savedStock addObject:dict];
// see what';s there now
for (NSDictionary *dict in savedStock) {
NSLog(#"my Note : %#",dict);
}
// now save out
[savedStock writeToFile:path atomically:YES];
}

how to store NSMutableArray in plist [duplicate]

This question already has answers here:
How to Save NSMutableArray into plist in iphone
(4 answers)
Closed 9 years ago.
I have NSMutableArray with name "add" that has in self name of cell (in UITableView)
I want store this "add" NSMutableArray in .plist file.
this is "add" code:
//NSArray *NaMe;
//NSMutableArray *add;
//NSMutableArray *all;
for (int i =0; i<11; i++) {
NSIndexPath *indexPath = [self.Table indexPathForSelectedRow];
NaMe = [[all objectAtIndex:(indexPath.row)+i]objectForKey:#"name"];
if(!add){
add = [NSMutableArray array];
}
[add addObject:NaMe];
}
NSLog(#"%#",add);
this add show me name of cell and I want store this name in .plist file.
I assume you want to save the plist for persistence.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = paths[0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"Names.plist"];
[add writeToFile:filePath atomically:YES];
To read back from plist
NSArray *array = [NSArray arrayWithContentsOfFile:filePath];
NSArray*pListpaths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString*pListdocumentsDirectory = [pListpathsobjectAtIndex:0];
NSString*pListpath = [pListdocumentsDirectory stringByAppendingPathComponent:#"Apps.plist"]; NSFileManager*pListfileMgr = [NSFileManager defaultManager];
//Create a plist if it doesn't alread exist
if (![pListfileMgrfileExistsAtPath: pListpath])
{
NSString*bundle = [[NSBundle mainBundle]pathForResource:#"Apps" ofType:#"plist"];
[pListfileMgrcopyItemAtPath:bundletoPath: pListpatherror:&error];
}
//Write to the plist
NSMutableDictionary*thePList = [[NSMutableDictionary alloc] initWithContentsOfFile: pListpath];
[thePList setObject:[NSString stringWithFormat:#"YourContent"] forKey:#"Related Key"];
[thePList writeToFile: pListpathatomically: YES];
Try This Sample Code
The solution is quite simple.
Create an NSArray containing your NSMutableArray, then write it to a path.
NSArray *yourArray=[NSArray arrayWithObjects:<#(id), ...#>, nil];
NSArray *yourPath = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libDir = [yourPath objectAtIndex:0];
NSString *loc = [libDir stringByAppendingString:#"/anyfilename.plist"];
[yourArray writeToFile:loc atomically:YES];
Fetch your array using:
yourPath = [bundle pathForResource:#"anyfilename" ofType:#"plist"];
yourArray = (yourArray!= nil ? [NSArray arrayWithContentsOfFile:loc] : nil);
user this code
#define DOC_DIR [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]
NSArray *NaMe;
NSMutableArray *add;
NSMutableArray *all;
for (int i =0; i<11; i++) {
NSIndexPath *indexPath = [self.Table indexPathForSelectedRow];
NaMe = [[all objectAtIndex:(indexPath.row)+i]objectForKey:#"name"];
if(!add){
add = [NSMutableArray array];
}
[add addObject:NaMe];
}
NSLog(#"%#",add);
[self writeDataToPlistFromArray:add];
-(void) writeDataToPlistFromArray:(NSArray *) dataArray
{
NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithObjectsAndKeys:dataArray,#"Root", nil];
NSString *path = [DOC_DIR stringByAppendingPathComponent:#"Names.plist"];
[dic writeToFile:path atomically:YES];
}

Resources