Index of NowPlayingItem is wronging when Shuffle Mode is on in iOS - ios

I'm now playing song from iPod Library that loaded into myArray with iPodMusicPlayer.
We can use indexOfNowPlayingItem to get index from NowPlaying music.
But when i Shuffle Mode is on, that indexOfNowPlayingItem Property's return index is completely wrong.
before ShuffleMode is off,indexOfNowPlayingItem can be used and correct.
However when ShuffleMode is on, indexOfNowPlayingItem count is only increase 1 (++).
like that
indexOfNowPlayingItem++;
Not a correct for ShuffleMode on.
So how can i get correct index when ShuffleMode on?
Thanks for your help.

My solution was when you set your playlist, set also a NSMutableDictionary with (index, MPMediaEntityPropertyPersistentID) of playlist.
When you need the song index, just get with the song persistent id.
- (void) setPlaylistIndexDictionary:(MPMediaItemCollection *)playlistItems
{
playlistIndexDict = [[NSMutableDictionary alloc] init];
NSNumber *count = [[NSNumber alloc] initWithInt:0];
for (MPMediaItem *item in [playlistItems items]) {
[playlistIndexDict setObject:count forKey:[item valueForProperty:MPMediaEntityPropertyPersistentID]];
count = [NSNumber numberWithInt:count.intValue + 1];
}
}
- (NSString *) getCurrentSongId
{
NSString* songId = [[musicPlayer nowPlayingItem] valueForProperty:MPMediaEntityPropertyPersistentID];
return songId;
}
Using:
NSString *songId = [musicController getCurrentSongId];
int songIndex = [[[musicController playlistIndexDict] objectForKey:songId] intValue];

Related

I need to have a mutable Array that has 8 interpolated strings in IOS

I'm new to IOS and I'm not sure if I'm on the right track. What I need to know is if I'm on the right track and if I'm off it a hint on what to fix so I can get back on track. The mutable Array should read an array of speakers and say "Hello, my name is <speakerArray>" it should do that 8 times with a different name each time. This is what I Have:
- (NSArray*)badgesForSpeakers:(NSArray*)speakers {
for(speakers i = 0; i => 7; i++)
{
NSString *greetings =#"Hello, my name is .";
NSMutableArray *badges = [speakers arrayByAddingObjectsFromArray:greetings];
}
return badges;
}
Let's take this one step at a time. First of all, your operator in the loop is wrong; you mean to execute while i is less than or equal to 7. Thus, change => to <=. However, it's more stylish to say i < 8. And finally, it's most stylish of all to use what's called "Fast Enumeration", which allows you to loop without an index at all. In fact, it will work no matter how many items are in your speakers array! That takes us here:
- (NSArray*)badgesForSpeakers:(NSArray*)speakers {
for (NSString* speaker in speakers)
{
NSString *greetings =#"Hello, my name is .";
NSMutableArray *badges = [speakers arrayByAddingObjectsFromArray:greetings];
}
return badges;
}
Next, greetings isn't an array! It's a string. That's why calling -arrayByAddingObjectsFromArray: doesn't make any sense, and why the compiler isn't going to like it. Let's make its name singular, greeting, to reflect this fact. Strategy: Your goal here is to create an empty array, then construct items one by one and add them to that array. That takes us to:
- (NSArray*)badgesForSpeakers:(NSArray*)speakers {
NSMutableArray *badges = [NSMutableArray array]; //Here we make an empty array
for (NSString* speaker in speakers)
{
NSString *greeting =#"Hello, my name is .";
[badges addObject:greeting]; //Here we add one item to it each time 'round the loop
}
return badges;
}
Last, your string has no interpolation right now! It reads literally "Hello, my name is ." We do string interpolation using the -stringWithFormat: method.
Finished Product:
- (NSArray*)badgesForSpeakers:(NSArray*)speakers {
NSMutableArray *badges = [NSMutableArray array];
for (NSString* speaker in speakers)
{
NSString *greeting = [NSString stringWithFormat:#"Hello, my name is %#.",speaker];
[badges addObject:greeting];
}
return badges;
}
That should get you started with fast enumeration and string interpolation. Remember to compile your code often and try to understand the compiler errors--it would have helped you with some of these issues.
Maybe you mean this
- (NSMutableArray *)badgesForSpeakers:(NSArray *)speakers {
NSMutableArray *badges = [[NSMutableArray alloc] init];
for (NSString *speaker in speakers) {
[badges addObject:[NSString stringWithFormat:#"Hello, my name is %#", speaker]];
}
return badges;
}
plz use this code
- (NSArray*)badgesForSpeakers:(NSArray*)speakers {
NSMutableArray *badges = [NSMutableArray alloc];
for(int i = 0; i < speakers.count; i++)
{
NSString *greetings =[NSString stringWithFormat:#"Hello, my name is .%#",[speakers objectAtIndex:i]];
badges = [speakers addObject:greetings];
}
return [badges copy];
}

how to add the button clicks and count in a dictionary

I have a method called addbuttonClicktocounter. When the function is called it should add the button name as key and number of clicks as count. I made this in my static library. When the user called these method again and again it should capture all the button names and number of clicks in one dictionary. If same button clicks again and again means the button name should remain same and the click count oly get increased. Here is my code what my tried upto my level:
NSMutableDictionary *BtnclicDict;
-(void) addButtonClickToCounter : (NSString*)button_Name button_click :(int)but_Click{
if([[BtnclicDict allKeys] containsObject:button_Name]){
int saveClick = [[BtnclicDict valueForKey:button_Name] integerValue];
but_Click = saveClick + but_Click;
NSNumber *click = [NSNumber numberWithInt:but_Click];
NSString *clickString = [click stringValue];
[BtnclicDict setObject:clickString forKey:button_Name];
NSLog(#"same button...,%#",click);
NSLog(#"same key dict...,%#",BtnclicDict);
} else {
NSString *but_Name = [NSString stringWithString:button_Name];
// NSLog(#"%#",but_Name);
NSNumber *click = [NSNumber numberWithInt:but_Click];
// NSLog(#"%#",click);
NSString *clickString = [click stringValue];
// BtnclicDict = [NSMutableDictionary dictionaryWithObject:but_Name forKey:click];
// BtnclicDict = [[NSMutableDictionary alloc]init];
[BtnclicDict setObject:clickString forKey:but_Name];
NSLog(#"working,%#",BtnclicDict);
// NSLog(#"%# Button Values...",BtnclicDict);
}
}
If you call this method from another class again and again it should collect all the details and make it into one dictionary.
You can try this.
-(void) addButtonClickToCounter : (NSString*)button_Name button_click :(int)but_Click{
if ([BtnclicDict valueForKey:buttonName])
but_Click += [[BtnclicDict valueForKey:button_Name] integerValue];
[BtnclicDict setValue:but_Click forKey:button_Name];
}

NSMutableArray, checking which Value is the most abundant?

How can I check which value in an NSMutableArray is the most frequent?
Array = "0,2,3,2,2,4
the value = "2".
Take a look at NSCountedSet this will help with your problem.
NSCountedSet *countedSet = [[NSCountedSet alloc] initWithArray:youArray];
NSInteger maxCount = 0;
id maxObject = nil;
for (id object in countedSet) {
if ([countedSet object] > maxCount) {
maxCount = [countedSet countForObject:object];
maxObject = object;
}
}
return maxObject;
This does sound like homework though.
EDIT
If they are stored as strings instead of numbers then swap out NSNumber for NSString everything else works the same.
EDIT
Actually, I just realised that it doesn't care about what object type it is...
Latest edit will work whatever the object is.

Determine minimum value in array and find corresponding string in another array

I have a 'winners screen' in a mini-golf scorecard app I'm making. I have two arrays that store 1). The player's names and 2). Their scores.
playerNameArray = [[NSMutableArray alloc]initWithObjects:playerOneName.text, playerTwoName.text, playerThreeName.text, playerFourName.text, playerFiveName.text, playerSixName.text, nil];
scoreArray = [[NSMutableArray alloc]initWithObjects:playerOneStat.text, playerTwoStat.text, playerThreeStat.text, playerFourStat.text, playerFiveStat.text, playerSixStat.text, nil];
I'm able to find the name of the player that scored the lowest with this:
int winner = [[scoreArray valueForKeyPath:#"#min.intValue"] intValue];
NSLog(#"the winner scored %d", winner);
NSString *string = [NSString stringWithFormat:#"%d", winner];
NSUInteger indexOfTheObject = [scoreArray indexOfObject:string];
NSString *playerString = [playerNameArray objectAtIndex:indexOfTheObject];
NSLog(#"The winner name is %#", playerString);
This works if there's only one player, but if there are two or more players that scored the same lowest score it can only display the name of the player that is first in the array order. How would I be able to modify the code to create a list/array of winners that share the same score?
Since you have two "parallel" arrays, perhaps the simplest thing is to have a loop, like this:
for (int i = 0 ; i != scoreArray.count ; i++) {
if (scoreArray[i].intValue == winner) {
NSLog(#"Winner %# at index %d.", playerNameArray[i], i);
}
}
If you followed a more traditional approach and created an object representing a player, say,
#interface Player : NSObject
#property (nonatomic, readonly) NSString *name;
#property (nonatomic, readonly) int score;
-(id)initWithName:(NSString*)name andScore:(int)score;
#end
then you would be able to use a predicate to do a search, and retrieve all winners in a single shot.
I would do it using NSMutableDictionary instead of two arrays.
//NSMutableDictionary to store player scores rather than two arrays
NSMutableDictionary *players = [NSMutableDictionary new];
//Each player name is a key with their score stored as an NSNumber
[players setObject:#(10) forKey:#"John"];
[players setObject:#(15) forKey:#"Tim"];
[players setObject:#(20) forKey:#"Phil"];
[players setObject:#(17) forKey:#"Kurt"];
[players setObject:#(19) forKey:#"Cory"];
[players setObject:#(10) forKey:#"Robert"];
//Find the lowest score out of the bunch
NSNumber *theLowestScore = [[players allValues] valueForKeyPath:#"#min.intValue"];
//There could be multiple lowest score players so this will get everyone that is associated with the lowest score
NSArray *playersWithLowestScores = [players allKeysForObject:theLowestScore];
//Print out the players name who have the lowest score
[playersWithLowestScores enumerateObjectsUsingBlock:^(NSString *playerName, NSUInteger idx, BOOL *stop) {
NSLog(#"%#", playerName);
}];
Just add a for loop to your code. Other things are fine. Have not tested the code though. Check for formatting errors:
int winner = [[scoreArray valueForKeyPath:#"#min.intValue"] intValue];
NSLog(#"the winner scored %d", winner);
NSString *string = [NSString stringWithFormat:#"%d", winner];
for (int i=0; i<scoreArray.count; i++) {
if ([scoreArray[i] isEqualToString:string]) {
[indices addObject:#(i)];
}
}
NSLog(#"%#",indices);
for (int i=0; i<indices.count; i++) {
//print all player names with lowest score
NSLog(#"The winner(s) are:");
NSLog(#"%#,",playerNameArray[indices[i].intValue]);
}

iPhone play a specific playlist/iMix

I want to play a specific playlist (that was constructed as an iMix) from my program, as long as it exists. I am able to use
[[MPMediaQuery albumsQuery] addFilterPredicate:[MPMediaPropertyPredicate predicateWithValue:#"MyAlbum" forProperty:MPMediaItemPropertyAlbumTitle]];
to get all songs in an album (as well as many other options for artists, etc.) but there seems to be no way to access playlists.
Is there a different way to do this, or will I be forced to store all the songs in the playlist within my code and access them all that way?
I haven't used it myself, but I see a [MPMediaQuery playlistsQuery] and MPMediaGroupingPlaylist in the docs...
Does this link help?
http://discussions.apple.com/thread.jspa?threadID=2084104&tstart=0&messageID=9838244
I ended up having to roll my own via a text file that contains playlist information. here is the code. The [Globals split] function just takes a string and splits it into an array of strings using either a single character ([Globals split: with:]) or each character in a string ([Globals split: withMany:]).
//Create the music player for our application.
musicPlayer = [MPMusicPlayerController applicationMusicPlayer];
[musicPlayer setShuffleMode: MPMusicShuffleModeOff];
[musicPlayer setRepeatMode: MPMusicRepeatModeAll];
//Get our song list from the text file.
NSError *error = nil;
NSString *songList = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"Playlist" ofType:#"txt"] encoding:NSUTF8StringEncoding error:&error];
//Split it into each song using newlines or carriage returns.
NSArray *allSongs = [Globals split:songList withMany:#"\r\n"];
NSMutableArray *music = [NSMutableArray arrayWithCapacity:[allSongs count]];
for (int i = 0; i < [allSongs count]; i++)
{
//Split the line into tab-delimited info: title, artist, album.
NSArray *songInfo = [Globals split:[allSongs objectAtIndex:i] with:'\t'];
//Get a query using all the data we have. This should return one song.
MPMediaQuery *songQuery = [MPMediaQuery songsQuery];
if ([songInfo count] > 0)
{
[songQuery addFilterPredicate:[MPMediaPropertyPredicate predicateWithValue:[songInfo objectAtIndex:0] forProperty:MPMediaItemPropertyTitle]];
}
if ([songInfo count] > 1)
{
[songQuery addFilterPredicate:[MPMediaPropertyPredicate predicateWithValue:[songInfo objectAtIndex:1] forProperty:MPMediaItemPropertyArtist]];
}
if ([songInfo count] > 2)
{
[songQuery addFilterPredicate:[MPMediaPropertyPredicate predicateWithValue:[songInfo objectAtIndex:2] forProperty:MPMediaItemPropertyAlbumTitle]];
}
//Add the song to our collection if we were able to find it.
NSArray *matching = [songQuery items];
if ([matching count] > 0)
{
[music addObject:[matching objectAtIndex:0]];
printf("Added in: %s\n",[(NSString *)[(MPMediaItem *)[matching objectAtIndex:0] valueForProperty:MPMediaItemPropertyTitle] UTF8String]);
}
else
{
printf("Couldn't add in: %s\n",[(NSString *)[songInfo objectAtIndex:0] UTF8String]);
}
}
//Now that we have a collection, make our playlist.
if ([music count] > 0)
{
itunesLoaded = YES;
// just get the first album with this name (there should only be one)
MPMediaItemCollection *itunesAlbum = [MPMediaItemCollection collectionWithItems:music];
//Shuffle our songs.
musicPlayer.shuffleMode = MPMusicShuffleModeSongs;
[musicPlayer setQueueWithItemCollection: itunesAlbum];
}
The text file is very easily generated using iTunes. All you need to do is create your playlist in iTunes, remove all the song info from your list except for Title, Artist, and Album, select all, and then paste into a text file. It will automatically be tab-delimitted and split by carriage returns. You also won't need to worry about mistyping or anything like that.

Resources