This is kind of weird! When I run the app on simulator it works fine but on the device it does not remove the tableHeaderView. Here is my code:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if(UITableViewCellEditingStyleDelete == editingStyle)
{
BOOL success = [Service deleteNoteByNoteId:note];
if(success)
{
[self updateTableViewHeader];
}
}
}
-(void) updateTableViewHeader
{
if([self.selectedVegetableGarden.notes count] > 0)
{
self.tableView.tableHeaderView = [self createSharingView];
}
else
{
self.tableView.tableHeaderView = nil;
}
}
The line self.tableView.tableHeaderView = nil gets triggered but it never removes the table header.
I don't think that is the right way to do it. You're nilifying a view that your table view is managing. Why don't you try instead returning either your custom view or nil form UITableViewDelegate's method - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section. I believe that's the right way to do it. You can ask the OS to call that method by executing the following line:
[self.tableView reloadData];
Hope this helps!
Related
I have 3 table views in one view and I was wondering why the tableView:cellForRowAtIndexPath: was not getting called.
#pragma mark -
#pragma mark <UITableViewDelegate>
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.mainVoucherTableViewController)
[self setSelectedIndex:indexPath.row];
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.mainVoucherTableViewController){
return 10;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.mainVoucherTableViewController){
static NSString *MyIdentifier = #"MyReuseIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier];
}
cell.textLabel.text = #"THISTEXT";
return cell;
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (tableView == self.mainVoucherTableViewController)
return 1;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
// The header for the section is the region name -- get this from the region at the section index.
if (tableView == self.mainVoucherTableViewController){
NSString * myString = [NSString stringWithFormat:#"HELLLO WORLD"];
return myString;
}
}
WOULD anyone know why this is? Basically this doesn't create any cell or display cells. It just displays the table views. :(
Just to consolidate a few things from above:
From your naming, your tableView is called mainVoucherTableViewController - just want to confirm that this is indeed a UITableView and not a UITableViewController? If it's a UITableViewController then the rest of this won't work for obvious reasons (or not so obvious - let me know and can explain further)
Make sure you have set the current viewController as the tableView's delegate and dataSource, either with the code below or in Interface Builder if you're using a XIB
self.mainVoucherTableViewController.delegate = self;
self.mainVoucherTableViewController.dataSource = self;
Make sure your numberOfRowsInSection function is being called and that you're returning non-zero (put in NSLogs, etc) and do the same for numberOfSections as well (actually numberOfSections isn't required if you're only using 1 section) - see UITableViewDataSource Protocol Reference: http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewDataSource_Protocol/Reference/Reference.html
As per previous post, log your cellForRow (if points #1-3 are checked and working) at the beginning to make sure it's triggered, and just before the return. Also do an NSLog of the cell you're returning just to make sure it isn't nil.
Start off by logging inside your tableView:cellForRowAtIndexPath: method to see if it gets called at all outside your if statement as well as inside to help narrow down the issue.
Also try instead of comparing your:
tableView == self.mainVoucherTableViewController
Set the tableViews to have tag values instead. Then you can do:
if(tableView.tag == 100){ // tag number we assigned self.mainVoucherTableViewController via IB
//do your stuff here
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.mainVoucherTableViewController)
{
return 10;
}
else
{retun 5;
}
}
It display row in first table 10, second table show 5 rows.
The order of instance declaration does matter. For example, if you have a ivar called tableView:
WRONG
self.tableView.delegate = self;
self.tableView = [UITableView alloc] init];
CORRECT
self.tableView = [UITableView alloc] init];
self.tableView.delegate = self;
check UITableView Object Frame Size. maybe Frame size is not enough to draw Cell.
I have googled and done lot of research from my side to find out why the reloadData method on tableview wouldn't work. I checked all the possible solutions like the datasource is set, delegate is set, the tableview is connected to the file's owner.
After all these, when I am trying to reload the tableview, the no. of rows method gets called, but the cell for rowAtIndexPath doesn't get called. Below is the code that I have written. Please let me know, where I am going wrong
- (void)onReservationListSuccess:(NSArray *)rData
{
if ( rData != nil )
{
resList = [[NSArray alloc] initWithArray:rData];
if([resList count] > 0)
{
[self.tripsTableView reloadData];
//[self.tripsTableView beginUpdates];
//[self.tripsTableView reloadSections:[NSIndexSet indexSetWithIndex:0]
// withRowAnimation:UITableViewRowAnimationNone];
//[self.tripsTableView endUpdates];
}
else
{
[tripsTableView reloadData];
[tripsTableView setHidden:YES];
[noTripsLabel setHidden:NO];
}
}
if(fsnNeedsRefresh == YES)
{
[[NSNotificationCenter defaultCenter] postNotificationName:UpdateFSNList object:nil];
fsnNeedsRefresh = NO;
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
int temp=[resList count];
NSLog(#"The no. of rows are %d", temp);
NSLog(#"Testing Purpose");
NSLog(#"The pnr details of the object is:%#",((TripData *)[resList objectAtIndex:0]).pnrDescription);
return 1;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"The cell for the row at indexpath is getting called");
static NSString *CellIdentifier = #"TripCellIdentifier";
TripCell *cell = (TripCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TripCell" owner:self options:nil];
for(id oneObject in nib)
if([oneObject isKindOfClass:[TripCell class]])
cell = (TripCell *)oneObject;
}
// Set up the cell...
TripData *tripData = (TripData *)[resList objectAtIndex:indexPath.row];
cell.pnrLabel.text = tripData.pnr;
NSLog(#"The cell text is %#",tripData.pnr);
cell.pnrDescriptionLabel.text = tripData.pnrDescription;
NSLog(#"The cell text is %#",tripData.pnrDescription);
cell.pnrTypeLabel.text = tripData.pnrType;
NSLog(#"The cell text is %#",tripData.pnrType);
if(checkInAllowed)
{
cell.checkInButton.tag = indexPath.row;
[cell.checkInButton addTarget:self action:#selector(checkIn:) forControlEvents:UIControlEventTouchUpInside];
}
else
{
[cell.checkInButton setEnabled:NO];
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller
TripData *tripData = (TripData *)[resList objectAtIndex:indexPath.row];
NSLog(#"%#", tripData.pnr);
if(tripData != nil)
{
TripOverviewViewController *tripOverviewViewController = [[TripOverviewViewController alloc] initWithTrip:tripData];
[self.navigationController pushViewController:tripOverviewViewController animated:YES];
[tripOverviewViewController release];
}
[tableView deselectRowAtIndexPath:indexPath animated:NO];
}
From this part of code I cannot say exactly why it does not work but I'll try to explain how reloadData works.
First, how UITableView works: basically, it's a scrollview. When it is drawn, it checks how many rows it has, then checks their height and from its size and scroll position it decides which rows are currently displayed. Then it asks the delegate to return a UITableViewCell for every displayed row.
When the table is scrolled, it removes the hidden cells from the view hierarchy and adds the cells that have appeared.
And now the tricky part - what does reloadData do? It just removes all the UITableViewCells from the table hierarchy. Nothing more. The actual update is done when the table is drawn for the first time after reloadData.
So, my suggestion is - check that your table is not hidden and check its frame. Also, I see that you are accessing both a property getter self.tripsTableView and an ivar tripsTableView. This is confusing. Do they both return the same?
Im working on a student project.
At this point our application can call the API and reload the data, but only if I call the XMLParser inside textDidChange.
Meaning: It calls and reloads correctly every time a letter is typed in UISearchBar. I Want the call and reload to only happen when the user clicks on the Search button, but the same code that works in textDidChange doesnt work in searchBarSearchButtonClicked.
Instead.. The method calls the API only when the searchbutton is pressed (good), recieves the the same information like with textDidChange (good) but doesnt reload the UITableView (bad).
I have searched all over SO for the answer to my problem, so I thought I'd post a question instead:)
All of the examples that I've come across only shows how to display the content of an array that matches the users criteria when the user types(contactlist), but doesnt show how to use the searchbutton to reload the uitableView correctly.
Why does the same exact code reload correctly in the delegate method
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
but not in
- (void)searchBarSearchButtonClicked:(UISearchBar *)theSearchBar?
As I said, NSLog prints out the correct data to load the uitableview when the searchButton is clicked, so that is not the problem.
Can anyone point me in the right direction here? :)
My cellForRowAtIndexPath:
`
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *uniqueIdentifier = #"searchCell";
SearchCell *cell = nil;
cell = (SearchCell *) [self.tableView dequeueReusableCellWithIdentifier:uniqueIdentifier];
if(!cell)
{
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"SearchCell" owner:nil options:nil];
for (id currentObject in topLevelObjects) {
if ([currentObject isKindOfClass:[SearchCell class]]) {
cell = (SearchCell *)currentObject;
break;
}
}
}
Search *currentSearch = [[searchxmlParser searchhits] objectAtIndex:indexPath.row];
cell.track_label.text = [currentSearch track];
cell.artist_label.text = [currentSearch artist];
return cell;
}
The requested delegate methods:
- (void)searchBar:(UISearchBar *)theSearchBar textDidChange:(NSString *)searchText {
NSString *searchurl = [NSString stringWithFormat:#"http://ws.spotify.com/search/1/track?q=%#", [self urlEncodeValue:searchText]];
xmlParser = [[SearchXMLParser alloc] loadXMLByURL:searchurl];
[self.tableView reloadData];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)theSearchBar {
NSString *searchurl = [NSString stringWithFormat:#"http://ws.spotify.com/search/1/track?q=%#", [self urlEncodeValue:theSearchBar.text]];
xmlParser = [[SearchXMLParser alloc] loadXMLByURL:searchurl];
[self.tableView reloadData];
[theSearchBar setShowsCancelButton:NO animated:YES];
[theSearchBar resignFirstResponder];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return [[searchxmlParser searchhits] count];
}
Thank you for your time! :)
You should use an UISearchDisplayController.
In your h file you should have declared 2 arrays one with the original dataSource and one with filtredValues. Alloc them in viewDidLoad and release in dealloc.
In cellForRowAtIndexPat and in umberOfRowsInSection you should test witch tableView is displayed and return desired values.
if(tableView == self.searchDisplayController.searchResultsTableView){
// search view population
} else {
// all data view population
}
And with this approach you can use live search by filtring dataSource array and put the values in filtredArray.
You need to set yourself as the delegate of search bar and override the default behavior of the delegate search bar delegate searchDisplayController:shouldReloadTableForSearchString:.
The default implementation of this will do a search with each key press. All you have to do is return NO in the method:
- (BOOL) searchDisplayController:(UISearchDisplayController *)controller
shouldReloadTableForSearchString:(NSString *)searchString {
return NO;
}
Did you correctly implement numberOfSectionsInTableView and numberOfRowsInSection ?
Please show the code for these two methods.
Addition:
If you put
NSLog(#" number of rows in section = %d", [[searchxmlParser searchhits] count]);
what does it output?
I have a UISearchDisplayController that is properly hooked up in Interface Builder.
delegate = Files Owner
searchBar = Search Bar
searchContentsController = Files Owner
searchResultsDataSource = Files Owner
searchResultsDelegate = Files Owner
When my UITableView calls numberoOfRowsInSection: the correct number is returned.
However, my cells in cellForRowAtIndexPath: don't even reach:
- (UITableViewCell *)tableView:(UITableView *)tblView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tblView == searchController.searchResultsTableView){
NSLog(#"search will go here");
UITableViewCell* cell = [self provideSearchQueryCells:tblView identifer:#"searchQueryCell"];
STSymbol *aSymbol = [self.searchQueryResults objectAtIndex:indexPath.row];
cell.textLabel.text = aSymbol.symbol;
cell.detailTextLabel.text = aSymbol.symbol_title;
return cell;
}
else { ... }
It always goes to the else condition.
I am not exactly sure why.
I needed to create an instance of a UISearchDisplayController instead of using self.searchDisplayController.
use the following. It should work.
if ([tblView isEqual:[searchController searchResultsTableView]]) {
...
}
you should also make sure the search result row count is correct as in :
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([tblView isEqual:[searchController searchResultsTableView]]) {
return [self.searchResults count];
}
...
}
This is a guess from this close in on the code, but are we looking at the search display controller itself? Maybe your self.searchDisplayController.searchResultsTableView should just be self.searchResultsTableView.
I can't be sure without knowing your delegates.
I've searched all over the web, and my code seems to be nearly identical to everything out there, but I can't get my UITableView editing to work for inserting a row. When I click the edit button, all of my existing rows get the delete control, but I get no additional row for insertion. I'm pulling my hair out for what seems like it should be a simple thing. What am I missing?
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
[categoryTV setEditing: editing animated:animated];
NSIndexPath *ip = [NSIndexPath indexPathForRow:[[appDelegate appCategories] count] inSection:0];
[self.categoryTV beginUpdates];
if (editing) {
[categoryTV insertRowsAtIndexPaths:[NSArray arrayWithObject:ip] withRowAnimation:UITableViewRowAnimationLeft];
} else {
[categoryTV deleteRowsAtIndexPaths:[NSArray arrayWithObject:ip] withRowAnimation:UITableViewRowAnimationFade];
}
[self.categoryTV endUpdates];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
...
if (indexPath.row >= [[appDelegate appCategories] count])
cell.textLabel.text = NSLocalizedString(#"New Category", #"NewCategoryCellText");
else
cell.textLabel.text = [[[appDelegate appCategories] objectAtIndex:indexPath.row] detailValue];
....
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (self.editing) {
return [[appDelegate appCategories] count] + 1;
} else {
return [[appDelegate appCategories] count];
}
}
As noted, I forgot to include my version of the suggested method, now shown below. Thanks.
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == [[appDelegate appCategories] count]) {
return UITableViewCellEditingStyleInsert;
} else {
return UITableViewCellEditingStyleDelete;
}
}
You need to implement the following delegate method to assign an editing style:
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleInsert;
}
Obviously you will only return that for the cell you want to have an insert control. Otherwise, you will need to return UITableViewCellEditingStyleDelete.
I saw similar behavior in my UITableView, and the problem was that my canEditRowAtIndexPath method returned NO for the insertion control row.
set tableview editing property YES
- (void)viewDidLoad {
.......
self.tableView.editing = YES; //set editing property of tableview
.......
}
editing - A Boolean value that determines whether the table view is in editing mode.
Declaration
#property(nonatomic, getter=isEditing) BOOL editing
Discussion
When the value of this property is YES, the table view is in editing
mode: The cells of the table might show an insertion or deletion
control on the left side of each cell and a reordering control on the
right side, depending on how the cell is configured. (See
UITableViewCell Class Reference for details.) Tapping a control causes
the table view to invoke the data source method
tableView:commitEditingStyle:forRowAtIndexPath:.
The default value is NO.
then return that cell in which you want to have an insert control
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleInsert;
}