How to know index of current Object with name - ios

I have an array called poemcollection
poemcollection = [[NSMutableArray alloc] initWithObjects:
[[NSBundle mainBundle] pathForResource:#"twinkle_twinkle" ofType:#"mp3"],
[[NSBundle mainBundle] pathForResource:#"baa_baa_black_sheep" ofType:#"mp3"],
[[NSBundle mainBundle] pathForResource:#"johny_johny" ofType:#"mp3"],
on button click
I want to know which object is playing currently from this array and index of this object.
I want to print in log this both name and index of current file playing on player

[poemcollection indexOfObject:YOUR_CURRENT_PLAYING_OBJECT];

Something like this?
-(void)printCurrentlyPlaying
{
NSString *mediaFileName = [[self.player.url absoluteString] lastPathComponent];
BOOL found = NO;
int poemIndex = -1;
for(int i = 0; i < poemcollection.count && !found; i++)
{
NSString *filePath = poemcollection[i];
NSString *fileName = [filePath lastPathComponent];
if([fileName isEqualToString:mediaFileName])
{
found = YES;
poemIndex = i;
}
}
if(found)
{
NSLog(#"Currently playing: %#, track number: %d", mediaFileName, poemIndex);
}
}

You can keep a mapping dictionary for the media name, e.g -
poemCollection = #[ #{"Twinkle twinkle": [[NSMutableArray alloc] initWithObjects:
[[NSBundle mainBundle] pathForResource:#"twinkle_twinkle" ofType:#"mp3"]},
#{#"Baa baa black sheep": [[NSBundle mainBundle] pathForResource:#"baa_baa_black_sheep" ofType:#"mp3"]},
#{"Johny Johny": [[NSBundle mainBundle] pathForResource:#"johny_johny" ofType:#"mp3"]}];
//And read the title like below :
NSString *title = [poemCollection[index] allKeys][0]
NSString *musicFile = [poemCollection[index] allValues][0]

try this code to get current file name and object.
NSString *currentFile = [[self.player.url absoluteString] lastPathComponent];
[poemcollection indexOfObject:currentFile];

Related

iOS use ID3Lib to edit ID3 tags from mp3 files in the NSDocsDir

I am using ID3Lib example project to edit Title, Album and Artist ID3 tags on mp3 files and all is good until I come to adding an image (cover Art) if any one has any ideas how to finish off the below code that would be great:
- (void)demo {
nImage = [UIImage imageNamed:#"amazing-grace.jpg"];//unused
NSString *imagePath = [[NSBundle mainBundle] pathForResource:#"amazing-grace" ofType:#"jpg"];
NSString *path = [[NSBundle mainBundle] pathForResource:#"amazing-grace-10s" ofType:#"mp3"];
NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = [[docPaths objectAtIndex:0] stringByAppendingPathComponent:#"amazing-grace-10s.mp3"];
[[NSFileManager defaultManager] copyItemAtPath:path toPath:docPath error:nil];
// Read title tag
ID3_Tag tag;
tag.Link([path UTF8String]);
ID3_Frame *titleFrame = tag.Find(ID3FID_TITLE);
unicode_t const *value = titleFrame->GetField(ID3FN_TEXT)->GetRawUnicodeText();
NSString *title = [NSString stringWithCString:(char const *) value encoding:NSUnicodeStringEncoding];
NSLog(#"The title before is %#", title);
// Write title tag
tag.Link([docPath UTF8String]);
tag.Strip(ID3FID_TITLE);
tag.Strip(ID3FID_ALBUM);
tag.Strip(ID3FID_LEADARTIST);
tag.Clear();
ID3_Frame frame;
frame.SetID(ID3FID_TITLE);
frame.GetField(ID3FN_TEXTENC)->Set(ID3TE_UNICODE);
NSString *newTitle = nTitle;
frame.GetField(ID3FN_TEXT)->Set((unicode_t *) [newTitle cStringUsingEncoding:NSUTF16StringEncoding]);
ID3_Frame frame2;
frame2.SetID(ID3FID_ALBUM);
frame2.GetField(ID3FN_TEXTENC)->Set(ID3TE_UNICODE);
NSString *newAlbum = nAlbmum;
frame2.GetField(ID3FN_TEXT)->Set((unicode_t *) [newAlbum cStringUsingEncoding:NSUTF16StringEncoding]);
ID3_Frame frame3;
frame3.SetID(ID3FID_LEADARTIST);
frame3.GetField(ID3FN_TEXTENC)->Set(ID3TE_UNICODE);
NSString *newArtist = nArtist;
frame3.GetField(ID3FN_TEXT)->Set((unicode_t *) [newArtist cStringUsingEncoding:NSUTF16StringEncoding]);
//this is the image code
ID3_Frame frame4;
frame4.SetID(ID3FID_PICTURE);
frame4.GetField(ID3FN_TEXTENC)->Set(ID3TE_UNICODE);// dont think this should be TEXTENC
NSString *newImage = imagePath;
frame4.GetField(ID3FN_DATA)->FromFile((const char *)[newImage cStringUsingEncoding:NSUTF16StringEncoding]);//this line is also probably wrong
tag.AddFrame(frame);
tag.AddFrame(frame2);
tag.AddFrame(frame3);
tag.AddFrame(frame4);
tag.SetPadding(false);
tag.SetUnsync(false);
tag.Update(ID3TT_ID3V2);
NSLog(#"The title after is %# The album after is %# The artist after is %# The artist after is %#", newTitle,newAlbum,newArtist,newImage);
}
Use file path with UTF-8 encoding and will work fine:
frame.GetField(ID3FN_DATA)->FromFile((const char *)[newImage cStringUsingEncoding:NSUTF8StringEncoding]);
I get this code, From this source: https://android.googlesource.com/platform/external/id3lib/+/8a58cac9f8db5ed55b02b3ac24156d628af923d1/examples/test_pic.cpp
frame.SetID(ID3FID_PICTURE);
frame.GetField(ID3FN_MIMETYPE)->Set("image/jpeg");
frame.GetField(ID3FN_PICTURETYPE)->Set(11);
frame.GetField(ID3FN_DESCRIPTION)->Set("B/W picture of Saint-Saƫns");
//frame.GetField(ID3FN_DATA)->FromFile("composer.jpg");
frame.GetField(ID3FN_DATA)->FromFile((const char *)[newImage cStringUsingEncoding:NSUTF8StringEncoding]);
tag.AddFrame(frame);
And! this work nice. :D

iOS plist is null

I know there are a multitude of questions about this on SO but I can't see where I am making the mistake and am hoping some extra eyes will help. I've verified the plist is in my bundle and it is also in my docs directory and it contains data. Here's a screen capture of the app package with the plist at top:
I pass the plist in from another class and have verified that it is the correct plist.
Here's my code:
-(id)init {
if (self = [super init]) {
//set up the appTracker
appTracker = [[OAI_AppTracker alloc] init];
//set up a file manager and error container
fileManger=[NSFileManager defaultManager];
//docs directory path
documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
//track event
appTracker.appEvent = #"File Manager initialized";
[appTracker recordEvent];
}
return self;
}
- (NSDictionary* ) readPlist {
NSError* error;
//set up dictionary to hold our app data
NSDictionary* appData;
//set up destination path
NSString* destinationPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#", plistToRead]];
if ([fileManger fileExistsAtPath:destinationPath]){
//read plist
appData = [[NSDictionary alloc] initWithContentsOfFile:destinationPath];
} else {
//file doesn't exist so we have to move it to the doc folder
NSString *sourcePath=[[[NSBundle mainBundle] resourcePath]stringByAppendingPathComponent:plistToWrite];
[fileManger copyItemAtPath:sourcePath toPath:destinationPath error:&error];
//now read the plist
appData = [[NSDictionary alloc] initWithContentsOfFile:destinationPath];
}
NSLog(#"%#", appData);
return appData;
}
My log shows NULL instead of the data in the plist. Appreciate any help as to what I am doing wrong.
To read your plist try something like this:
NSString *plistPath = [[NSBundle mainBundle] pathForResource:#"PlistFileName" ofType:#"plist"];
NSDictionary *plistData = [[NSDictionary alloc] initWithContentsOfFile:plistPath];

iOS release not working as expected

I am using this code to get book names from a config.plist file. However my memory management is problematic. The '[dict release]' breaks the app completely and it exits.
The code works when the '[dict release]' is removed but it causes memory leaks as far as I can tell.
bnames is a global NSMutableArray
What am I doing wrong?
- (NSString *)loadBookname: (NSInteger) bookToLoad {
bookToLoad = [self bookOrder:bookToLoad];
//---get the path to the property list file---
plistFileNameConf = [[self documentsPath] stringByAppendingPathComponent:#"Config.plist"];
//---if the property list file can be found---
if ([[NSFileManager defaultManager] fileExistsAtPath:plistFileNameConf]) {
//---load the content of the property list file into a NSDictionary object---
dict = [[NSDictionary alloc] initWithContentsOfFile:plistFileNameConf];
bnames = [dict valueForKey:#"BookNames"];
[dict release];
}
else {
//---load the property list from the Resources folder---
NSString *pListPath = [[NSBundle mainBundle] pathForResource:#"Config" ofType:#"plist"];
dict = [[NSDictionary alloc] initWithContentsOfFile:pListPath];
bnames = [dict valueForKey:#"BookNames"];
[dict release];
}
plistFileNameConf = nil;
NSString *bookNameTemp;
bookNameTemp = [bnames objectAtIndex:bookToLoad - 1];
NSLog(#"bookName: %#", bookNameTemp);
return bookNameTemp;
}
You need to allocate your array properly:
bnames = [[NSArray alloc] initWithArray:[dict valueForKey:#"BookNames"]];
Double check that your dict returns the right data type.
There does not appear to be anything wrong with the way you allocate NSDictionary (although you could also use the [NSDictionary dictionaryWithContentsOfFile:] and save yourself having to worry about the release.
Either way I would suggest the issue is not with the [release] but probably the line BEFORE release:
bnames = [dict valueForKey:#"BookNames"];
a) Where is that allocated. I don't see an allocation or declaration of it anywhere?
b) What type of value do you expect back?
Put a break point on it and make sure your getting what you expect or anything.
If dict is not already a strong property, make it one. Then, use self.dict when assigning to it (and keep the release).
I've found what appears to be a better solution to the issue. This lets iOS manage the memory.
//---finds the path to the application's Documents directory---
- (NSString *) documentsPath {
NSLog(#"Start documentsPath");
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
// NSLog(#"Found documentsPath 40");
NSLog(#"End documentsPath");
return documentsDir;
}
- (NSString *) configPath {
NSLog(#"Start configPath");
NSString *plistFileNameConf = [[self documentsPath] stringByAppendingPathComponent:#"Config.plist"];
if (![[NSFileManager defaultManager] fileExistsAtPath:plistFileNameConf]) {
plistFileNameConf = [[NSBundle mainBundle] pathForResource:#"Config" ofType:#"plist"];
}
NSLog(#"plistFile: %#",plistFileNameConf);
NSLog(#"End configPath");
return plistFileNameConf;
}
The following calls the above code as necessary:
NSString *Choice;
NSArray *properties;
NSString *errorDesc = nil;
NSPropertyListFormat format;
NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:[self configPath]];
NSDictionary *temp = (NSDictionary *)[NSPropertyListSerialization propertyListFromData:plistXML mutabilityOption:NSPropertyListMutableContainersAndLeaves format:&format errorDescription:&errorDesc];
if (!temp) {
NSLog(#"Error reading plist: %#, format: %d", errorDesc, format);
}
Choice = [temp objectForKey:#"Choice"];
properties = [temp objectForKey:Choice];

Plist to NSDictionary

I have some plist data like the one on the below image:
How do I access the "Text" value, if an NSDate equal to CDate is selected on my UIDatePicker?
So you basically want
NSString* path = [[NSBundle mainBundle] pathForResource:#"file" ofType:#"plist"];
NSArray* a = [NSArray arrayWithContentsOfFile:path];
for (NSDictionary *d in a)
{
NSString *cdate = [d objectForKey:#"CDate"];
if ([cdate isEqualToString:#"Whatever is currently selected"])
{
NSString *text = [d objectForKey:#"Text"];
// do something with text here
}
}
Stumbled across this and thought an update was due
NSDictionary *initialDefaults = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"Defaults" ofType:#"plist"]];

Load data EXC BAD ACCESS (only device)

When my custom data is loading on iPhone (3G, with 3.1) I get Exc Bad Access
in this line:
NSMutableArray* dataArr = [NSKeyedUnarchiver unarchiveObjectWithFile:pathGG]; //=EXC BAD ACCESS
On Ipad, and on simulator work
I saving data in simulator (to documentsDirectory path), then replace data to project, and load from [NSBundle mainBundle]
In array I use NSValue for store CGPoint.
Full source:
-(void) SaveData:(NSMutableArray*)dataLevel {
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documentsDirectory = [paths objectAtIndex:0];
NSString* fileName = #"data.dat";
NSString* pathGG = [documentsDirectory stringByAppendingPathComponent:fileName]; // retain];
BOOL isWrite = [NSKeyedArchiver archiveRootObject:dataLevel toFile:pathGG];
if(isWrite) NSLog(#"YES");
else NSLog(#"!!!");
}
+(NSMutableArray*) LoadData {
NSString* fileName = #"data.dat";
NSString* pathGG = [[NSBundle mainBundle] pathForResource:fileName ofType:#"dat"]; // retain];
NSMutableArray* dataA = [NSKeyedUnarchiver unarchiveObjectWithFile:pathGG]; //EXC BAD ACCESS
return dataA;
}
If I am using follow way(saving/loading same method), I get EXC BAD ACCESS too:
NSKeyedUnarchiver* decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
NSArray* dataArr = [decoder decodeObjectForKey:#"dataLevel"]; //EXC BAD ACCESS
Try this:
NSString* pathGG = [[documentsDirectory stringByAppendingPathComponent:fileName] retain];
Then when you are finished with it:
[pathGG release]
SOLUTION: Instead of store CGPoint in NSValue, use CGPointFromString(after NSStringFromCGPoint), and then add string to array.
NSString* positionStr = NSStringFromCGPoint(someCGPoint);
[someArray addObject:position];
// Now, saving array to file
...
//After loading array from file
CGPoint positon = CGPointFromString([someArr objectAtIndex:0]);

Resources