I have a UITableView where I set the height to be larger than default (using heightForRowAtIndexPath. The image in the cell is always 32x32 and us currently being vertically aligned to center. I'd like that the image will be at the top of the cell. I tried something like this (setting the bounds explicitly):
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:MyIdentifier] autorelease];
cell.imageView.bounds = CGRectMake(7,7,32,32);
....
}
....
}
but this doesn't work. Any simple way to make it without creating a complete custom cell?
Take a look at this article here
You can do some pretty custom modifications if you play with the content view, you just need to know how to do it ;)
Related
So I'm trying to add a UITableView on the lower half of my ipad app which will be used to display a search result. This is how I did it.
I added a UIView
I added a UItableView onto the UIView
I then dragged the UITableView to the ViewController so it can connect to it for delegate and datasource.
This is what it currently looks like:
(It's at that middle top row)
So I added the following onto the viewcontroller class to generate the data
# pragma mark TableView properties
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 2;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"SearchResultCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = #"test";
}
The debugger would go through all these but would get stuck after the "cellForRowAtIndexPath" method:
It would just go through that and would not end until I stop the whole debugging. Not really sure what's going on.
Thoughts? Maybe you guys can point me to the right direction as to how I should generate my search results.
Thanks!
I usually find it much more faster and easier to use the free Sensible TableView framework to do automatic table view searches, instead of using the regular datasource/delegate system which I could never get right.
I am creating the cell programatically using the reuse identifier.
Note - I am not using storyboard for creating the cell
Whenever the cell is dequeued, the cell is nil, so the cell needs to be newly created using alloc, which is expensive.
EDIT (added 1 more question and corrected code)
Question
Why does this dequeue always return nil ? How can I correct it ?
Does dequeue work only when used along with storyboard / nib file ?
Code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(!cell) //Every time cell is nil, dequeue not working
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
return cell;
}
You need to first set the CellIdentifier as Cell. Are you doing that? When you are creating a new cell you need to assign this identifier Cell to it. only then iOS will be able to dequeueReusableCellWithIdentifier with that identifier. Programatically you can do it like so -
UITableViewCell *cell = [[UItableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:#"Cell"];
You can set identifier from Interface Builder too -
I was making a couple of mistakes:
I was using a subclass of UITableViewController, but was creating the tableView outside of the subclass
There is a tableView created in the table view controller, which is self.tableView In the tableview controller while returning the cell for index path, I was using self.tableView instead of tableView.
Also, ensure that the cell identifier is declared as static
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
Since tableView and self.tableView were representing different tables, the cell was not being dequeued from the same table and hence was always nil
This code should be generating the warning "control reaches end of non-void function" because you aren't actually returning anything. Add return cell; to the end of the function. Additionally, you never add the reuse identifier to the newly created cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
return cell;
}
First declare cell identifier for a tableViewCell at the viewDidLoad method as:
[tableView registerClass:UITableViewCell.class forCellReuseIdentifier:#"MyCell"];
Now recall the instance of the UITableViewCell with the same identifier "MyCell" as:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MyCell" forIndexPath:indexPath];
Further just fill up the cell .. Now logic executes that limited number of cells are able to show enormously large list efficiently (using dequeue concept).
But remember to assign value (even nil if required) to every UIView used in the cell, otherwise overwriting / overlapping of text / images will happen.
I have a problem with my tableview. When I scroll and a cell disappears from the screen it becomes blank. I have built a prototype cell in the storyboard with two labels and one imageview, it have the same identifier that I use in my code. I also have built a custom class for the customcell. Here is the code in cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
Scientist *currentScientist = [[xmlParser data] objectAtIndex:indexPath.row];
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.self.cellName.text = currentScientist.self.name;
cell.self.cellSubject.text = currentScientist.self.subject;
cell.self.cellImage.image = currentScientist.self.image;
return cell;
}
I don't know if you need more code to help me.
In my case, creating a different cell identifier for each one worked just fine. I have something like:
NSString *cellIdentifier = [NSString stringWithFormat:#"identifier%i%i", indexPath.section, indexPath.row];
The rest should remain the same.
I found an article that details the problem you are encountering. I would also recommend printing out the Scientist data to ensure an object is being fetched correctly with the objectAtIndex:indexPath.row call.
From the article I linked below, I would be willing to bet that your dequeueReusableCellWithIdentifier is the problem. One quick way you could solve this is by giving each cell its' own unique cell identifier (Just to test out the theory). However, it looks the appropriate way to solve this is by changing up your cellForRowAtIndex method.
Source
Here is the CellForRowAtIndexPath method of UITableViewDataSource protocol. I saw that code on a website.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *TableIdentifier = #"SimpleTableItem";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:TableIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TableIdentifier];
}
cell.textLabel.text = [playersReady objectAtIndex:indexPath.row];
return cell;
}
My questions are:
Why when here defined cell wrote = [tableView dequeueReusableCellWithIdentifier:TableIdentifier]; ? What that means? If I commented that code everything going OK. For what that code? Hmmm...
How cell in if statement can be equals to nil if cell equals to TableIdentifier (SimpleTableItem)? For what wrote that code?
Why TableIdentifier equals to SimpleTableItem? For What?
An iPhone doesn't have a lot of memory. But even on modern computers you wouldn't want to initialize a new cell for every cell in your table. That's just wasting memory. So instead Apple came up with this idea of reusable cells. You only have to initialize a few cells that fill your screen (table view). Then, when the user scrolls down some new cells will appear at the bottom of the screen, but at the same time other cells will disappear at the top of the screen. So you can simply take those cells and reuse them.
Luckily UITableView manages this for you. All you have to do when you need to setup a new cell in that method is ask the table view, if it has any cells available that can be reused. If there are reusable cells, dequeueReusableCellWithIdentifier: will return one of them. But if there are non available yet (typically when you first fill up your table view with the initial cells) it will return nil. So you have to test if cell is nil and create a new cell from scratch if that's the case.
On iOS 6.0 there is a new method dequeueReusableCellWithIdentifier:forIndexPath: that always returns a valid cell (it creates the cell for you if there is no reusable cell yet).
Table view Create only those cell which can Display at one time on screen.After this system reuse cell for save memory .
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 20;
}
-(UITableViewCell *)tableView:(UITableView *)tableViewL cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableViewL dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
NSLog(#"Cell == nil so create a new cell....");
}else {
NSLog(#"Reuse Cell ");
}
return cell;
}
CellIdentifier use for identify cell for example if you add label on first ten table on 12 cell you add a button it give you a problem when you reuse cell.so that we need create a different cell For add button on cell and give it a Identifier string.
I have a UIView that gets added to my UITableView.view as a subview. It looks great and works fine, but when I scroll on my UITableView, the subview gets chopped up and disappears but only part of it (mostly the part that scrolls off). I can get it to come back on by calling:
[self.view bringSubviewToFront:self.myView];
but I'd rather not have to call this whenever the UITableView scrolls. Is there something I'm doing wrong? Thanks in advance.
Try this ..
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:nil] autorelease];
}
}
It's hard to tell what you end goal is but adding a subview to UITableView is kind of counter intuitive. The UITableView manages it's subviews (UITableViewCell's) and they are probably taking precedence over your subview. Are you looking for backgroundView?