How to allow duplicate entries in a table view - objective-c

I want to be able to load a playlist with duplicate song titles into a table view. However when the playlist is selected the table view automatically removes the duplicates? How do I prevent this and allow the duplicates to show in the table view?
This is the code I am using:
- (void) updatePlayerQueueWithMediaCollection: (MPMediaItemCollection *) mediaItemCollection
{
// Configure the music player, but only if the user chose at least one song to play
if (mediaItemCollection)
{
if (_userMediaItemCollection == nil)
{
self.userMediaItemCollection = mediaItemCollection;
[[GVMusicPlayerController sharedInstance ] setQueueWithItemCollection: _userMediaItemCollection];
if (array == nil)
{
[self savePlaylist:[MPMediaItemCollection collectionWithItems: self.userMediaItemCollection.items]];
}
else
{
[array addObjectsFromArray:self.userMediaItemCollection.items];
[self savePlaylist:[MPMediaItemCollection collectionWithItems: array]];
}
}
else
{
NSMutableArray *currentSongsList= [[_userMediaItemCollection items] mutableCopy];
NSArray *nowSelectedSongsList = [mediaItemCollection items];
[currentSongsList addObjectsFromArray:nowSelectedSongsList];
self.userMediaItemCollection = [MPMediaItemCollection collectionWithItems:(NSArray *) currentSongsList];
// Apply the new media item collection as a playback queue for the music player.
[[GVMusicPlayerController sharedInstance ] setQueueWithItemCollection: _userMediaItemCollection];
[[GVMusicPlayerController sharedInstance] pause];
//save playlist
[array addObjectsFromArray:_userMediaItemCollection.items];
[self savePlaylist:[MPMediaItemCollection collectionWithItems: array]];
}
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//this method is called to fill out table with data
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil)
{
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"Cell"];
}
// populate the cell from array
anItem = nil;
anItem = [array objectAtIndex:indexPath.row];
// Configure the cell
cell.textLabel.text = [anItem valueForProperty:MPMediaItemPropertyTitle];
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
return cell;
}

Related

Why my tableView did not display anything

i want select over 50 in the first section,and others in the second section ,but there is no value display in tableView ,and when i use NSlog("%#",self.over50) ,there is no reaction
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"UITableViewCell" ];
NSArray* items = [[BNRItemStore shareStore] allItems];
self.itemsUnder50 = [[NSMutableArray alloc] init];
self.itemsOver50 = [[NSMutableArray alloc] init];
for (BNRItem *item in items) {
if (indexPath.section ==0) {
[self.itemsOver50 addObject:item];
cell.textLabel.text = [self.itemsOver50[indexPath.row] description];
NSLog(#"%#",self.itemsUnder50);
}
else if(indexPath.section == 1){
[self.itemsUnder50 addObject:item];
cell.textLabel.text = [self.itemsUnder50[indexPath.row] description];
}
}
return cell;
}
connect the datasource and delegate of the tableview to the viewController

Filtered data doesn't show in my UITableView Objective C iOS7

I am trying to bind "Search Bar and Search Display Controller" in my UITableView. Filtered array has the right data but it doesn't display in tableview. When I enter something in search bar it displays blank table view.
In function "cellForRowAtIndexPath" when it binds the correct data but still doesn't show up. In the same function I also changed the code from
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"PersonCell" forIndexPath:indexPath];
to
UITableViewCell *cell = [self.personTableView dequeueReusableCellWithIdentifier:#"PersonCell" forIndexPath:indexPath];
then it throws the following exception:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Person length]: unrecognized selector sent to instance 0x1780ca170'
Code:
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [self.filteredPersonArray count];
} else {
return [self.personArray count];
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"PersonCell" forIndexPath:indexPath];
Person *person;
if (tableView == self.searchDisplayController.searchResultsTableView) {
person = (Person *)[self.filteredPersonArray objectAtIndex:indexPath.row];
} else {
person = (Person *)[self.personArray objectAtIndex:indexPath.row];
}
UILabel *nameLabel = (UILabel *)[cell viewWithTag:1];
nameLabel.text = [NSString stringWithFormat:#"%# %#", person.firstName, person.lastName];
// so on;
return cell;
}
-(void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope {
// Update the filtered array based on the search text and scope.
// Remove all objects from the filtered search array
[self.filteredPersonArray removeAllObjects];
// Filter the array using NSPredicate
NSPredicate *lastNamepredicate = [NSPredicate predicateWithFormat:#"SELF.lastName contains[c] %#",searchText];
//NSPredicate *firstNamePredicate = [NSPredicate predicateWithFormat:#"SELF.firstName contains[c] %#",scope];
//tempArray = [tempArray filteredArrayUsingPredicate:lastNamepredicate];
self.filteredPersonArray = [NSMutableArray arrayWithArray:[self.personArray
filteredArrayUsingPredicate:lastNamepredicate]];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller
shouldReloadTableForSearchString:(NSString *)searchString {
// Tells the table data source to reload when text changes
[self filterContentForSearchText:searchString scope:
[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:
[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
// Return YES to cause the search result table view to be reloaded.
return YES;
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller
shouldReloadTableForSearchScope:(NSInteger)searchOption {
// Tells the table data source to reload when scope bar selection changes
[self filterContentForSearchText:self.searchDisplayController.searchBar.text scope:
[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]];
// Return YES to cause the search result table view to be reloaded.
return YES;
}
Solution to this problem:
I referred to different tableview objects while creating the cell in case of
1. Loading the data after search
2. Loading the data in tableview
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell;
Person *person;
if (tableView == self.searchDisplayController.searchResultsTableView)
{
cell = [self.personTableView dequeueReusableCellWithIdentifier:#"PersonCell"];
person = (Person *)[self.filteredPersonArray objectAtIndex:indexPath.row];
} else {
cell = [tableView dequeueReusableCellWithIdentifier:#"PersonCell"];
person = (Person *)[self.personArray objectAtIndex:indexPath.row];
}
UILabel *nameLabel = (UILabel *)[cell viewWithTag:1];
nameLabel.text = [NSString stringWithFormat:#"%# %#", person.firstName, person.lastName];
// so on;
return cell;
}

Multidimensional array object for table view cell selected

I have a dictionary of arrays, and each of these arrays has a number of arrays itself. Its a multidimensional array in a dictionary.
When I click on a UItable row, I push the view to another class, however I want to push along with the view, the array whose object key is the same as the row name that was clicked.
My code is as follows
(The class that does the pushing)
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Navigation logic -- create and push a new view controller
if(dvController == nil)
dvController = [self.storyboard instantiateViewControllerWithIdentifier:#"FoodCategoryView"];
//NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
//NSMutableDictionary *keysAndObjects = [defaults objectForKey:#"keysAndObjects"];
Food *foodObj;
/*for (id key in [keysAndObjects allKeys]) {
NSArray *foodArray = [keysAndObjects objectForKey:key];
foodObj = [foodArray objectAtIndex:indexPath.row];
}*/
/*for (id key in [keysAndObjects allKeys]) {
NSArray *foodArray = [keysAndObjects objectForKey:key];
for (Food *food in foodArray) {
// do stuff with Food object
//NSLog(#"%#", food.foodName);
}
}*/
NSMutableArray *objects2 = [[NSMutableArray alloc] init];
NSMutableArray *objects1 = [[NSMutableArray alloc] init];
objects1 = [objects objectAtIndex:indexPath.row];
objects2 = [objects1 objectAtIndex:indexPath.row];
foodObj = objects2;
//NSLog(#"Object %#", [objects objectAtIndex:indexPath.row]);
NSLog(#"foodObj %#", foodObj);
//Get the detail view data if it does not exists.
//We only load the data we initially want and keep on loading as we need.
//[foodObj hydrateDetailViewData];
dvController.foodObj = foodObj;
[self.navigationController pushViewController:dvController animated:YES];
}
(the class that the view is pushed to)
- (UITableViewCell *)tableView:(UITableView *)tblView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier];
}
/*for (Food *food in foodObj) {
// do stuff with Food object
NSLog(#"%#", food.foodName);
cell.text = food.foodName;
}*/
//Food *food = [foodObj objectAtIndex:indexPath.row];
//cell.text = [foodObj objectAtIndex:indexPath.row];
cell.text = foodObj.foodName;
NSLog(#"%#", foodObj.foodName);
return cell;
}
As you can see there are lots of comments as I have tried lots of different ways to do it myself.

Search Bar for UITableView: I would like it to search through both textLabels and detailTextLabels (iOS 5.0, xcode 4.2)

I have set up a search bar for my table view, and I would like to have it search through both the textLabels (main text), and detailTextLabels (underlying text), while maintaining the relationship between the main labels and detail labels when narrowing down the search. Right now, I can search through the main labels only, but the detail labels will not stay with the related main labels. I have two arrays that carry the strings for the main labels and the detail labels. Here is some code.
The initialization of the arrays carrying the main labels (groceryStores) and the detail labels (groceryStoreAddresses), as well as the search array
- (void)viewDidLoad
{
[super viewDidLoad];
self.groceryStores = [NSArray arrayWithObjects:#"Safeway",#"Grocery Store 1",#"Grocery Store 2",#"Grocery Store 3",#"Grocery Store 4",#"Grocery Store 5",#"Grocery Store 6",#"Grocery Store 7",nil];
self.groceryStoreAddresses = [NSArray arrayWithObjects:#"1444 Shattuck Place, Berkeley, CA 94709",#"Address 1",#"Address 2",#"Address 3",#"Address 4",#"Address 5",#"Address 6",#"Address 7",nil];
self.searchGroceryStores = [NSMutableArray arrayWithCapacity:[self.groceryStores count]];
}
The search method
- (BOOL) searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self.searchGroceryStores removeAllObjects] ;
for (NSString *groceryStore in self.groceryStores) {
NSRange result = [groceryStore rangeOfString:searchString options:
NSCaseInsensitiveSearch];
if (result.location != NSNotFound)
[self.searchGroceryStores addObject:groceryStore];
}
return YES;
}
Rows in section tweaked for search functionality
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [self.searchGroceryStores count];
}
else {
return [self.groceryStores count];
}
}
cellForRowAtIndexPath tweaked for search functionality
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"UITableViewCellAccessoryDisclosureIndicator"];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
if (tableView == self.searchDisplayController.searchResultsTableView) {
cell.textLabel.text = [self.searchGroceryStores objectAtIndex:indexPath.row];
cell.detailTextLabel.text = [self.groceryStoreAddresses objectAtIndex:indexPath.row];
}
else {
cell.textLabel.text = [self.groceryStores objectAtIndex:indexPath.row];
cell.detailTextLabel.text = [self.groceryStoreAddresses objectAtIndex:indexPath.row];
}
// Configure the cell...
return cell;
}
Please help if you can. Thank you so much for your time, I appreciate it.
You need to keep a searchGroceryStoreAddresses array in parallel with your searchGroceryStores array. Example:
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self.searchGroceryStores removeAllObjects];
[self.searchGroceryStoreAddresses removeAllObjects];
for (int i = 0, c = self.groceryStores.count; i < c; ++i) {
NSString *groceryStore = [self.groceryStores objectAtIndex:i];
NSString *address = [self.groceryStoreAddresses objectAtIndex:i];
NSRange result = [groceryStore rangeOfString:searchString options:
NSCaseInsensitiveSearch];
if (result.location != NSNotFound) {
[self.searchGroceryStores addObject:groceryStore];
[self.searchGroceryStoreAddresses addObject:address];
}
}
return YES;
}

Calendars in array out of scope after filtering

I am making a little program that will put some events in a calendar on the iPhone. In the settings I will let the user select wich calendar to use. To present what calendars he can use I pull all calendars from the EKEventStore and sort out those that doesn't allow modifications. Those are subscribed from other websites.
After the filter, wich seems to be OK, the array is reduced from 5 to 3 calendars, all objects in the array are out of scope, and the list in the tableview is blank.
What am I missing?
Edit: The problem erupted when I started with the filtering, thats why I thought that was the problem, but now it seems that the objects go out of scope when the -(NSArray*)availableCalendar returns the array. Do I need to copy it or something?
Image here: http://d.pr/35HY
-(NSArray*)availableCalendars{
NSArray *calendars;
EKEventStore *eventDB = [[[EKEventStore alloc]init]autorelease];
calendars = [[[NSArray alloc]initWithArray:[eventDB calendars]]autorelease];
return calendars;
}
- (void)viewDidLoad {
[super viewDidLoad];
allcalendars = [self availableCalendars];
[allcalendars retain];
localCalendars = [[NSMutableArray alloc]initWithArray:allcalendars];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"allowsContentModifications == YES"];
[localCalendars filterUsingPredicate:predicate];
calendarCountInt = localCalendars.count; //When I break the code here, the three objects are 'Out of Scope' and the count is three
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
if (calendarCountInt > 0)
{
cell.textLabel.text = [[localCalendars objectAtIndex:indexPath.row] title] ;
}
else {
cell.textLabel.text = #"No Calendars found";
}
return cell;
}
- (void)dealloc {
[localCalendars release];
[allcalendars release];
[super dealloc];
}
Your code is ... interesting. I'm guessing that you're doing return calendarCountInt; in your tableView:numberOfRowsInSection: method. If you are, then that's going to return 0; when there are no calendars that allow modification, resulting in an empty table.
Here's how I would do it:
// this requires an #property(nonatomic, retain) NSArray *allCalendars
// with a corresponding NSArray *allCalendars ivar
// also, an #property(nonatomic, retain) NSArray *localCalendars
// with a corresponding NSArray *localCalendars ivar
// get all calendars and cache them in an ivar (if necessary)
- (NSArray *)allCalendars {
if (allCalendars == nil) {
EKEventStore *eventDB = [[[EKEventStore alloc] init] autorelease];
[self setAllCalendars:[eventDB calendars]];
}
return allCalendars;
}
// get all modifiable calendars and cache them in an ivar (if necessary)
- (NSArray *)localCalendars {
if (localCalendars == nil) {
NSPredicate *filter = [NSPredicate predicateWithFormat:#"allowsContentModifications == YES"];
[self setLocalCalendars:[[self allCalendars] filteredArrayUsingPredicate:filter]];
}
return localCalendars;
}
// there's only one section
- (NSUInteger)numberOfSectionsInTableView:(UITableView *)aTableView {
return 1;
}
// show the number of modifiable calendars, or 1 (if there are no modifiable calendars)
- (NSUInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSUInteger)section {
NSArray *local = [self localCalendars];
return ([local count] > 0) ? [local count] : 1;
}
// set up the cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
if ([[self localCalendars] count] > 0) {
cell.textLabel.text = [[[self localCalendars] objectAtIndex:[indexPath row]] title];
} else {
cell.textLabel.text = #"No calendars found";
}
}
- (void)dealloc {
[localCalendars release], localCalendars = nil;
[allCalendars release], allCalendars = nil;
[super dealloc];
}