Reputation: 2312
I have an indexed tableView
that displays a list of songs from the user's iPod library. But the sections start with 1, 2, etc., because I have songs that start with numbers. How do I group all songs that start with a number into a section '#' in my index?
Right now this is my app (left) compared to what I'd like it to be (right, Music.app). I've highlighted where the # should go (at the end of my index):
This is my code so far in my viewDidLoad
:
songsQuery = [MPMediaQuery songsQuery];
songs = [songsQuery items];
NSMutableDictionary *songsInitials;
songsInitials = [[NSMutableDictionary alloc]init];
self.alphabetArray = [[NSMutableArray alloc] init];
for (int i=0; i< songs.count; i++)
{
NSString *firstletter=[[[songs objectAtIndex:i] valueForProperty:MPMediaItemPropertyTitle] substringToIndex:1];
if (songsInitials[firstletter] == nil) {
songsInitials[firstletter] = [[NSMutableArray alloc] init];
[self.alphabetArray addObject:firstletter];
}
[songsInitials[firstletter] addObject:songs[i]];
}
[self.alphabetArray sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; //sorting array in ascending array
self.songsInitials = songsInitials;
....and my tableView
data source:
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return _alphabetArray.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_songsInitials[_alphabetArray[section]] count];
}
-(NSString *)titleForRow:(NSIndexPath *)indexpath{
NSString *firstLetter = _alphabetArray[indexpath.section];
MPMediaItem *myItem = [_songsInitials[firstLetter] objectAtIndex:indexpath.row];
return [myItem valueForProperty:MPMediaItemPropertyTitle];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView{
return self.alphabetArray;
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index{
NSIndexPath *indexpath;
for (int i=0; i < self.alphabetArray.count; i++)
{
NSString *titleToSearch=[self.alphabetArray objectAtIndex:i]; //getting sectiontitle from array
if ([title isEqualToString:titleToSearch]) // checking if title from tableview and sectiontitle are same
{
indexpath=[NSIndexPath indexPathForRow:0 inSection:i];
// scrolling the tableview to required section
[self.songsTable scrollToRowAtIndexPath:indexpath atScrollPosition:UITableViewScrollPositionTop animated:YES];
break;
}
}
return indexpath.section;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
cell.textLabel.text= [self titleForRow:indexPath]; //getting cell content
return cell;
}
This is what I've tried so far, adjusting the for loop
in viewDidLoad
:
for (int i=0; i< songs.count; i++)
{
NSString *firstletter=[[[songs objectAtIndex:i] valueForProperty:MPMediaItemPropertyTitle] substringToIndex:1];
if (songsInitials[firstletter] == nil) {
NSString *songsInitialsFirstLetter = songsInitials[firstletter];
if ([self stringIsNumeric:songsInitialsFirstLetter]){
songsInitials[firstletter] = [[NSMutableArray alloc] init];
[self.alphabetArray addObject:[NSString stringWithFormat:@"#"]];
NSLog(@"There are numbers!");
}
else if (![self stringIsNumeric:songsInitialsFirstLetter]){
songsInitials[firstletter] = [[NSMutableArray alloc] init];
[self.alphabetArray addObject:firstletter];
}
}
[songsInitials[firstletter] addObject:songs[i]];
}
-(BOOL) stringIsNumeric:(NSString *) str {
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
NSNumber *number = [formatter numberFromString:str];
return !!number; // If the string is not numeric, number will be nil
}
...but it didn't work. I've searched around but I can't find any other questions that ask this, am I missing something obvious here? Any help would be much appreciated! :)
Upvotes: 1
Views: 306
Reputation: 849
Did not test but changing first letter before looking in the arrays would give better result. After the sort, not sure where the symbol (#) will end tough, you may have to manual push it to the end.
for (int i=0; i< songs.count; i++)
{
NSString *firstletter=[[[songs objectAtIndex:i] valueForProperty:MPMediaItemPropertyTitle] substringToIndex:1];
NSScanner *ns = [NSScanner scannerWithString:firstletter];
if ( [ns scanInt:NULL] )
{
firstLetter = @"#";
}
if (songsInitials[firstletter] == nil) {
songsInitials[firstletter] = [[NSMutableArray alloc] init];
[self.alphabetArray addObject:firstletter];
}
[songsInitials[firstletter] addObject:songs[i]];
}
Upvotes: 1