Custom cell and UITableViewCell problems - iphone

Newbie here, just learning!
I'm trying to create a table view app with just three custom cells. Each cell needs to have an a label and an image on the left (so far I've only bothered with the label part). So far this guide
has been very useful. I created an array with three items and got it to load just fine, but when I tried to implement a custom cell everything broke. For this portion of code:
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"CustomCell";
CustomCell *cell = (CustomCell *)
[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil){
NSArray *topLevelObjects = [[NSBundle mainBundle]
loadNibNamed:#"CustomCell"
owner:nil options:nil];
for(id currentObject in topLevelObjects)
{
if ([currentObject isKindOfClass:[UITableViewCell class]])
{
cell = (CustomCell *) currentObject;
break;
}
}
}
cell.issue.text = array objectAtIndex:[indexPath.row];
return cell;
}
I get the errors Unused variable CellIdentifier, CustomCell undeclared, Expected expression before ) token and Control reaches end of non-void function.
I don't know what would cause these and I'm kind of at a dead end as far as my knowledge of what to look for. Sorry for my newbness, and any pointing in the right direction would be appreciated.
edit:
Heyooo! Thanks, importing CustomCell fixed a ton of the problems! Now there are no visible errors before running it, but when I try and run it, I just get sent to
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [array count];
with a red arrow pointing to return [array count];
The current array code I have is:
- (void)viewDidLoad {
[super viewDidLoad];
array = [[NSMutableArray alloc] init];
[array addObject:#"Eleven"];
[array addObject:#"Ten"];
[array addObject:#"Nine"];
Wow, what a helpful and responsive community. Can't thank you enough.

All you need is import declaration of CustomCell class.
#import "CustomCell.h" // for example.

You probably just missed a step. Have you made CustomCell.m, CustomCell.m and CustomCell.xib files? If so, you will need to import the header file.
#import "CustomCell.h"

Related

Object sent - autorelease too many times, getting this leak for my iPhone app?

I am getting too many Object sent - autorelease too many times, this memory leak for my iPhone app and dont know how to resolve it
http://screencast.com/t/fPzMNewvq
Above is screen shot for the same.
SAAdvertiseCell has lot of objects which are releasing, so how is it possible to find where the exact problem is?
Thanks
At first why don't you reuse cells?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
Cell* cell = [tableView dequeueReusableCellWithIdentifier:cell_id];
if(!cell)
{
cell = // create new cell;
}
// configure cell
return cell;
}
And for your problem: seems that initWithData: already returns an autoreleased object, then you send another autorelease. So check that method to find the problem.
For creation of Custom UITableViewCell, write your code in this manner:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"MyTableViewCellId";
MyTableViewCell *cell = (MyTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"MyTableViewCell" owner:self options:nil];
cell = [topLevelObjects objectAtIndex:0];
}
// write your code to customize cell or providing data content
return cell;
}
Hope this will help you to solve your problem

Using multiple custom cells without reusing identifier

I feel like a real noob asking this, but here's my problem:
I want to show a tableView, with 7 custom cells. None of these cells is reused. That means the user will see 7 different cells, not more, not less.
I created the cells in the viewDidLoad method, and added all those cells in the listCells-array. After that, I used easy-mode to draw those cells:
UITableViewCell *cell = nil;
if (indexPath.row == 0)
{
static NSString *MyIdentifier = #"Cell";
cell = (DetAlertCell *)[localTableView dequeueReusableCellWithIdentifier:nil];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"DetAlertCell" owner:self options:nil];
cell = [listCells objectAtIndex:indexPath.row];
}
}
....
However, this won't work. It shows me a blank view. Every cell is created using a .xib-file and a .h and .m class. Is there anything that I'm missing and should do?
Just don't call the [localTableView dequeueReusableCellWithIdentifier:nil] and loa the correct cell for the index path.
Also you say that you load the cells in the viewDidLoad, then why do you load the nib:
[[NSBundle mainBundle] loadNibNamed:#"DetAlertCell" owner:self options:nil];
They should already be the array should they not.
And why to you check if the row is 0 then load the row, still will only load the first row.
Try this:
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
return [listCells objectAtIndex:indexPath.row];
}

dequeueReusableCellWithIdentifier:identifier not picking up a loadNibNamed cell

I have a simple cell - designed in IB - and with the reuseIdentifier set. Below code works quite nicely. HOWever - the NSLog() reveals that the results are never cached.
Table view controller class:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
switch/case for various cell types
{
Foo * item = [results objectAtIndex:indexPath.row];
return [MyCell tableView:tableView populatedCellWith:item];
}
}
MyCell class..
+(UITableViewCell *)tableView:(UITableView *)tableView populatedCellWith:(Foo *)item
{
static NSString * identifier = #"XXX";
MyCell *cell = (MyCell *) [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
NSArray * items = [[NSBundle mainBundle] loadNibNamed:#"MyCell"
owner:self options:nil];
cell = [items objectAtIndex:0];
assert( cell && [cell.reuseIdentifier isEqualToString:identifier]);
NSLog(#"That was a load - rather than a nice cache for %#", self.class);
}
fill out some stuff.
return cell;
}
Why is this - as it makes things a lot more efficient ?
Thanks,
Dw.
The way you create the table view cell can not make sure to put the cell into the reusable queue in table view. Only way to do that is to use
initWithStyle:reuseIdentifier:
Initializes a table cell with a style and a reuse identifier and returns it to the caller.
My another question
Are you sure the cells have been set with a cell identifier? UITableView will not cache those without.

iphone how to access a custom cell outside of cellForRowAtIndexPath

i have set up a tableview with custom cells. customCell is a class.
heres the code for a more accurate view:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSManagedObject *object = (NSManagedObject *)[entityArray objectAtIndex:indexPath.row];
NSString *cellIdentifier = [NSString stringWithFormat:#"asd%d", indexPath.row];
customCell *cell = [[tableView dequeueReusableCellWithIdentifier:cellIdentifier] autorelease];
//i tried setting a tag but dunno how to call it afterwards
[cell setTag:indexPath.row];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"customCell" owner:self options:nil];
cell = [topLevelObjects objectAtIndex:0];
}
if (cell.imagen != nil) {
[[cell imageView] setImage:[cell imagen]];
} else { /* setup image... */ }
}
-(void) webImageReady:(WebImage *)downloadedImage imageView:(UIImageView *)imageView cellTag:(NSInteger *)cTag
{
// This is the part where i want to access cell.imagen, this is actually wrong...
[[[imageView.superview viewWithTag:cTag] imagen] setImagen:downloadedImage.Image];
[imageView setImage:downloadedImage.Image];
}
Ok. now i want to access (reference) the cell.imagen property from a method outside cellForRowAtIndexPath, more precisely at a selector for a download finished (delegated)
Thanks in advance!
Do it inside cellForRowAtIndexPath if the image is downloaded, and on successful download of the image do [tableview setNeedsDisplay]
You shouldn't refer to the cell outside the cell creation method, you should consider the case the cell was rendered but while getting the image was scrolled out the dealloced or even reused for another cell, one way to solve it is to have image view array or something similar.
I think you should try using a third party lib that already doing it(among other things) called Three20. It have an object call TTImageView that gets a URL and loads it in the background, it solves all of the cases along with optimized caching

iPhone table view - problem with indexPath.row

I'm using indexPath.row do determine in which row of my tableview I do something. The title of my cells is containing a number which should be 1 in the first row and 18 in the last row, so I have 18 rows. This works for the first 11 rows, but after that, I have numbers in the title which seem to be generated randomly! Sometimes 16, then 5, then 18, then 12... and so on.
What's the problem with it/why does the indexPath.row variable behave like that?
My cellForRowAtIndexPath method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"myCell" owner:self options:nil];
cell = cell0;
self.cell0 = nil;
}
UILabel *label;
label = (UILabel *)[cell viewWithTag:1];
label.text = [NSString stringWithFormat:#"Cell %d", indexPath.row];
return cell;
}
Any more suggestions on how to solve the problem? I didn't get it working until now...
// Update with more code:
Here is how I declare the cell. It is in an XIB file (template "empty XIB") in which I just put the cell from the library in IB.
#interface myViewController : UITableViewController {
UITableViewCell *cell0;
}
#property (nonatomic, retain) IBOutlet UITableViewCell *cell0;
Then, at the top of the myViewController.m file:
#synthesize cell0;
My cellForRowAtIndexPath method is already posted above. It is equal to the cellForRowAtIndexPath method in the SDK documentation, and in Apple's example, it seems to work.
What are you trying to accomplish with cell0?
cell = cell0;
self.cell0 = nil;
It looks like you're creating a new cell, but somehow deciding to use an old one. The real culprit looks like the code that is loading the cell actually getting assigned anywhere.
Try just this instead:
if (cell == nil) {
cell = [[NSBundle mainBundle] loadNibNamed:#"myCell" owner:self options:nil];
}
Or perhaps:
if (cell == nil)
{
// TODO: try to avoid view controller
UIViewController *vc = [[UIViewController alloc] initWithNibName:#"IndividualContractWithResult" bundle:nil];
cell = (IndividualContractWithResult_Cell *) vc.view;
[vc release];
}
To would be easier to answer if you give the code where you create cells for your table view. It looks that there's a problem with reusing cells - you reuse previously created cells without setting a new value to it.
It sounds like you are not re-using cells but creating new ones when there are cells available. Look at the sample code for dequeueReusableCellWithIdentifier.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MyCell"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:#"MyCell"] autorelease];
}
cell.text = <your code here>;
return cell;
}
It would seem that you're incorrectly accessing a property here:
cell = cell0;
self.cell0 = nil;
Assuming that you have an instance variable named cell0, by setting it to nil, you may be releasing it before you're ready to use it.
The proper way to do this is:
cell = self.cell0;
self.cell0 = nil;
This way, if cell0 is declared as retain, you'll automatically get an autoreleased cell0 back, whereas if you reference cell0 directly (no self.), you'll get an unretained reference, which will disappear when self.cell0 = nil is called.
The advantage of using a nib-based cell here is that you can use outlets, rather than tags, to identify subviews. You've done the heavy lifting already, you might want to just add an outlet and subclass UITableViewCell to get access to the label.
You will need to retain and autorelease cell0, otherwise when you set self.cell0 = nil, then cell0 has no known references.
cell = [[cell0 retain] autorelease];
self.cell0 = nil;
You can also do this:
cell = self.cell0;
self.cell0 = nil;
.. Since any retain properties should implement their getters with the retain/autorelease pattern.