Xcode - IF statement fails in heightForRowAtIndexPath - iphone

This is what I currently have:
In cellForRowAtIndexPath
if ([userSelection isEqualToString:comparison]){
changeHeight = NO;
} else if(![userSelection isEqualToString:comparison]) {
[cell setHidden:YES];
changeHeight = YES;
}
return cell;
Here is the heightForRowAtIndexPath
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(changeHeight == YES) {
return 0;
} else return 44;
changeHeight = NO;
}
The if statement is the cellForRowAtIndexPath works perfectly, but the one in the heightForRowAtIndexPath doesn't evaluate and always returns 44 - no matter is the equality in cellForRowAtIndexPath is true or not.
Any ideas?

You are not holding state correctly and are making the assumption that heightForRowAtIndexPath will be called immediately after cellForRowAtIndexPath is called. That might be true, but I would expect the order of calling to be undefined and it might not even be calling with respect to the same cell.
So you need to keep state on a per-cell basis, rather than a single "changeHeight" flag.
Now I cannot design all that for you, but you simply need to extend your model data to hold what you want the height of each cell to be.
Also think about what this statement does (it's not related to your question, but you still need to sort it out):
if ([userSelection isEqualToString:comparison]){
} else if(![userSelection isEqualToString:comparison]) {
}

Basically heightForRowAtIndexPath is get called just before cellForRowAtIndexPath. It's better to do like below.
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return ([userSelection isEqualToString:comparison])?44.0f:0.0f;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
[cell setHidden:![userSelection isEqualToString:comparison]];
/* Your stuff */
}

heightForRowAtIndexPath is called before cellForRowAtIndexPath. Hence changeHeight does not have correct state. And think about trojanfoe's question with your if...else.

Related

Two UITableViewCell with different identifier and different height in storyboard

I have two type of cells that I'll be using my UITableView, so I created two prototype cell with different identifier. I manuelly changed the size but when I compile and run, the two cells have same size.
Is there any way to do it through storyboard and without checking every single time
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
I will have around a good 100 cells at least.
UPDATE: in my case I have a tableview with 3 sections, the first one is small, the second and the third one are bigger.
I think your best option is to use that -tableView:heightForRowAtIndexPath: delegate method you listed and return the height you would like.
You could assign tags to each prototype and use an if/else if conditional.
Or if you have a subclassed UITableViewCell for each prototype you could do something like
...
id cell = [tableView cellForRowAtIndexPath:indexPath];
if ([cell isKindOfClass:[CustomCell1 class]]) {
// return aNumber;
} else if ([cell isKindOfClass:[CustomCell2 class]]) {
// return aNumber;
} else {
return aNumber;
}
...
If you know that the sections if what determines the height of the cell, then you can implement it like this:
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath*)indexPath {
CGFloat result;
if (indexPath.section == 0) {
result = 160;
} else {
result = 80;
}
return result;
}
Depending on the heights that you need of course.

UITableView tableView:cellForRowAtIndexPath: not getting called

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.

UISearchDisplayController is not displaying any cells

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.

UISearchDisplayController changing row height

I've set my UITableView row height to in Interface Builder to 54.0. I have a UISearchDisplayController on that view. When the user taps the search bar in it, the table resizes properly. However, when they start typing (and actually doing the search) the row height decreases. It stays wrong until the search taps Cancel.
I could find no documentation on this behavior on Apple's site.
I've tried setting the row height in UISearchDisplayDelegate delegate calls. This might be the right approach, but I don't know the details and couldn't get it to work.
I've also tried implementing - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;. This worked, but I have thousands of entries in this list and can't take the performance hit.
What's the right way to fix this?
The correct way to do this is to use the following delegate.
- (void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView
{
tableView.rowHeight = 54.0f; // or some other height
}
It's called when the UITableView is created or shown.
If you happen to call searchDisplayController.searchResultsTableView in other code when a search is not being performed, it will create the UITableView in advance. If you use the willShow delegate method to set the rowHeight, it will miss the timing (for some reason) to change the rowHeight if the tableView has been created beforehand.
I found it!
Assuming the table is stored in tableView:
- (void)viewDidLoad;
{
[super viewDidLoad];
self.searchDisplayController.searchResultsTableView.rowHeight = tableView.rowHeight;
}
Nothing else is necessary.
Edit: See netmikey's answer for a better solution.
Steve, your solution didn't work for me: The first time the search result would display fine, but when a user was hitting "Cancel" (closing away the search bar) and then reopening it and entering a search term into it, the height would be wrong again.
DigDog's solution of using searchDisplayController:didShowSearchResultsTableView was kinda working, but users saw the cell height "jumping" when the search started.
The solution I found, that fixed both these issues is using:
- (void)searchDisplayController: (UISearchDisplayController *)controller
willShowSearchResultsTableView: (UITableView *)searchTableView {
searchTableView.rowHeight = myTableView.rowHeight;
}
... in the UISearchDisplayDelegate.
Regards,
netmikey
In viewDidLoad:
you can set the search display controller's delegate to self:
- (void)viewDidLoad
{
self.searchDisplayController.delegate = self;
}
Then, implement the table view delegate in your view controller:
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableview == self.searchDisplayController.tableView) {
return 55;
} else if (tableView == self.tableView) {
return 44;
}
}
Overriding the method didLoadSearchResultsTableView should do the trick.
- (void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView {
tableView.rowHeight = 82.0; // Change height of search result row
}
More explanation from this blog
You need to set both
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 54.;
}
and
self.tableView.rowHeight = 54.;
also in your UISearchDisplayDelegate
- (void)searchDisplayController:(UISearchDisplayController *)controller didShowSearchResultsTableView:(UITableView *)tableView {
tableView.rowHeight = 54.;
}
Otherwise, when "No Result" happened in searching, cell height will fall back to default.
I've been using ios 7.0 and Xcode 5.0. I think you should change you row height in this method:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
if (tableView == self.searchDisplayController.searchResultsTableView)
{
tableView.rowHeight = ...;// change your row height here!
return [self.searchResults count];
}
else
{
...
return ...;
}
}
Because every time a tableview try to display its layout, this method is called, so everytime you type a letter into search bar, this method is called,and the row height won't have a chance to change.
None of the solutions worked for me...
Did my own hit and trial... and got it working...
If you want different row heights for normal & search table views...
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
// for normal results
if (tableView==self.tableView) return 54;
// for search results
else return 54; }
And if you want common height...
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 54; }
PS: Do keep in mind, if you have same row height for each row, this method is not very efficient resource usage wise, as the row height is re-calculated for each cell... Although, this is unnoticeable in most cases, I am still searching for a better solution!

How to prevent UITableView from reserving space at the left of cell when editing is turned on?

I'm set editing mode for UITableView to have a possibility of cell reordering. UITableViewCellEditingStyleNone is returned by editingStyleForRowAtIndexPath: method for every cell, but it reserve some area on the left of cell. Is it possible to prevent such an area reserving, because I'm not need an insert or delete icon on left? In short, i want have a cell that occupate all available area and still can be reordered.
// UITableViewDelegate
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath {
return NO;
}
See the docs: You can set a boolean on the cell to make it not indent. Just add
cell.shouldIndentWhileEditing = NO;
to wherever you create your cell.
Set this to like 2 or 3
tableView:indentationLevelForRowAtIndexPath:
The shouldIndentWhileEditing property only works with grouped tables. I found that setting an indentation level of -3 does the job for plain tables. Is there a better way? Here's what I'm using now:
if (self.tableView.style == UITableViewStylePlain) {
cell.indentationLevel = -3;
} else if (self.tableView.style == UITableViewStyleGrouped) {
cell.shouldIndentWhileEditing = FALSE;
}
Do both
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath {
return NO;
}
and
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleNone;
}
in your UITableViewDelegate. Otherwise the cell content is indented.