You can assume my cell is complicated enough, In order to reduce the coupling, I want implement the cell by child MVC, my sample code like this:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
CellViewController *cellVC = [[NSBundle mainBundle] loadNibNamed:#"CellViewController" owner:self options:nil].lastObject;
[self addChildViewController:cellVC];
[cell.contentView addSubview:cellVC.view];
cellVC.view.frame = cell.bounds;
}
return cell;
my cellViewController has a function - updateUIWithModel:
now, my question is:
1) using MVC like this is right?
2) if right, how can i set the data to cellVC?
You need to add UITableViewDataSource,and use an NSMutableArray to set the data to cellVC.
Related
I am new to developing. i have some experience but i'm not great at it (yet). I'm working on this tableview app which shows data. I want to show that data in a custom cell. But i don't know how to do that.
This is the code i use for my tableview:
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
HistoryTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"HistoryViewTableCell"];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"HistoryViewTableCell" owner:self options:nil];
cell = [topLevelObjects objectAtIndex:0];
}
NSDictionary * tempDictionary = [tableData objectAtIndex:indexPath.row];
cell.textLabel.text = [tempDictionary objectForKey:#"PickupAddress"];
return cell;
}
I need to show this line of code in my custom cell.
cell.textLabel.text = [tempDictionary objectForKey:#"PickupAddress"];
I already made a class and a xib file for the custom cell
This may solve the problem:
HistoryTableViewCell *cell = (HistoryTableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"HistoryViewTableCell"];
your written kind of code will not work. if you are using custom XIB than add a UILable in the xib. and than assign them tag number.
now from ViewController do the following:
write this after #implementation
enum {
CELL_TITLE = 2,
CELL_SUBTITLE_1 = 3,
};
Load the Custom XIB File in cellforrowatindexpath method.
// Get table View Cell
static NSString *CellIdentifier = #"customCell";
UITableViewCell *cell = [atableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib;
nib = [[NSBundle mainBundle] loadNibNamed:CellIdentifier owner:self options:nil];
cell = (UITableViewCell *) [nib objectAtIndex:0];
}
Now Add text on Lable with the below methods;
UILabel *titleLable = (UILabel *) [cell.contentView viewWithTag:CELL_TITLE];
titleLable.text = #"This is your text";
I'm having some problem with multiple custom UITableViewCell reuse. I have 3 types of custom UITableViewCell. I tried to reuse the UITableViewCell using dequeueReusableCellWithIdentifier.
I wrote the prepareForReuse and made all possible subviews data nil. But still I was getting some repetitions of data in some UITableViewCell's. So I was thinking of reusing just the xib without any data.
I made up the following code. The app seems to have some freezing problem now. Somebody please show me the correct way to reuse tableview UITableViewCells without data repetition.
static NSString *cellIdentifier = #"SystemListCell";
IXSystemMessageCustomCell *cell = (IXSystemMessageCustomCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[[NSBundle mainBundle] loadNibNamed:#"IXSystemMessageCustomCell" owner:self options:nil] objectAtIndex:0];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
IXSystemMessageCustomCell *cellToSave = cell;
[self configureSystemCell: cellToSave atIndexPath:indexPath];
return cellToSave;
Do not modify the data in prepareForReuse
A better way is to
dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath
We should always modify the data in cellForRowAtIndexPath as this helps in reuse of cells.
Also, since you have created IXSystemMessageCustomCell class it is better to use this :
[[IXSystemMessageCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]
and write the setup code in initWithStyle:reuseIdentifier:
instead of this:
cell = [[[NSBundle mainBundle] loadNibNamed:#"IXSystemMessageCustomCell" owner:self options:nil] objectAtIndex:0];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
Cheers!
You can use 3 different reuse identifier for your 3 cell types:
IXSystemMessageCustomCell *cell;
if (some condintion) {
cell = (IXSystemMessageCustomCell *)[tableView dequeueReusableCellWithIdentifier:"CellReuseIdentifierType1"];
} else if (some condition 2) {
cell = (IXSystemMessageCustomCell *)[tableView dequeueReusableCellWithIdentifier:"CellReuseIdentifierType2"];
} else {
cell = (IXSystemMessageCustomCell *)[tableView dequeueReusableCellWithIdentifier:"CellReuseIdentifierType3"];
}
In this case you don't need to re-configure cell each time for each cell type
Try this...
IXSystemMessageCustomCell *cell = nil;
cell = (IXSystemMessageCustomCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
By setting your cell to nil first, you are clearing out previous data associated with the reused cell.
Also register your nib once in your viewDidLoad or similar table view lifecycle method, so that this is not required at every call to tableView:cellForRowAtIndexPath.
So extract your static call from any method to be a private declaration...
static NSString *cellIdentifier = #"SystemListCell";
and adjust your methods to read...
- (void)viewDidLoad {
UINib *nib = [UINib nibWithNibName:#"IXSystemMessageCustomCell" bundle:nil];
[<<self.tableView>> registerNib:nib
forCellReuseIdentifier:cellIdentifier];
<< ... other code ... >>
}
and
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
IXSystemMessageCustomCell *cell = nil;
cell = (IXSystemMessageCustomCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
[self configureSystemCell:cell atIndexPath:indexPath];
return cell;
}
cell=[tableView dequeueReusableCellWithIdentifier:identifier];
if([ActivityStreamArray count]>[indexPath row])
{
GlobalMethod *LocalMethod = [ActivityStreamArray objectAtIndex:[indexPath row]];
if (cell == nil)
{
cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
if([[LocalMethod ActivityType] isEqualToString:#"photos"])
{
UIView *BackView=[[[NSBundle mainBundle] loadNibNamed:#"ActivityExtendedDesign" owner:self options:nil] objectAtIndex:12];
CGRect TempBackRect=[BackView frame];
TempBackRect.origin.x=0.0f;
//TempBackRect.size.height+=ExtraHeightForImage;
[BackView setFrame:TempBackRect];
[cell addSubview:BackView];
}
I am working on a web base application where I load content in tableview from an extended xiv. This xiv contents views for my tableview cell. Tableview loads different content for different cell .The problem is that when I use dequeueReusableCell. The content did not show when scroll up.
That's how, I think should be implemented as in your implementation above, only when your cell is nil, you are comparing LocalMethod's ActivityType and if it equals to "photos" then you are adding Backview to the uitablviewcell but when the cell is dequeued the it already contains Backview which is not what you want, if I am not mistaken you want to compare LocalMethod's ActivityType again and add other view if it is not equal to "photos".
cell=[tableView dequeueReusableCellWithIdentifier:identifier];
GlobalMethod *LocalMethod = [ActivityStreamArray objectAtIndex:[indexPath row]];
if (cell == nil)
{
cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
if([[LocalMethod ActivityType] isEqualToString:#"photos"])
{
UIView *BackView=[[[NSBundle mainBundle] loadNibNamed:#"ActivityExtendedDesign" owner:self options:nil] objectAtIndex:12];
CGRect TempBackRect=[BackView frame];
TempBackRect.origin.x=0.0f;
//TempBackRect.size.height+=ExtraHeightForImage;
[BackView setFrame:TempBackRect];
[cell addSubview:BackView];
}
I've seen this problem with many others, went thru all the topics, but I can't seem to find a solution for it.
So I have a normal table view, with a cell linked to a .xib file, at first launch everything looks normal, but once I start scroll the app crashes immediately.
By enabling zombie objects I got to this error:
2012-05-03 16:18:13.008 coop_dev[27547:f803] * -[ActivityTableViewController tableView:cellForRowAtIndexPath:]: message sent to deallocated instance 0x6853990
But I'm not sure what to look for or what might go wrong:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
ItemCell *cell = (ItemCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"ItemCell" owner:nil options:nil];
cell = [topLevelObjects objectAtIndex:0];
}
Item *item = [self.activity objectAtIndex:indexPath.row];
[[cell projectLabel] setText:item.project];
[[cell descriptionLabel] setText:item.description];
[[cell timeLabel] setText:item.time];
[[cell timeAgoLabel] setText:item.timeAgo];
//cell.avatar = [UIImageView item.avatar];
cell.descriptionLabel.numberOfLines = 0;
[cell.descriptionLabel sizeToFit];
// remove the right arrow
cell.accessoryType = UITableViewCellAccessoryNone;
return cell;
}
It works fine at first launch but after that just crashes
EDIT
I re-created the problem in a new project, just a basic table with some data, once you start scrolling it crashes. Download: http://dl.dropbox.com/u/274185/TestTable.zip
In your FirstViewController.xib, remove the UITableViewController, but leave the UITableView. The crash happens because the File's Owner is already set as class FirstViewController in the Identity Inspector and it's like you have a second UITableViewController. Make sure also that the UITableView is hooked to the view outlet of the controller.
You are dequeueing code is a bit off... try mine:
UITableViewCell *cell = [[UITableViewCell alloc] init];
cell = nil;
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"cell"]
autorelease];
cell.imageView.image = nil;
cell.textLabel.text = nil;
}
Check your ItemCell class' dealloc method, you're probably overreleasing something.
I do not understand why my cell.detailTextLabel.text is null.
static NSString *CellIdentifier = #"Cell";
//UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyId];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
/*[[NSBundle mainBundle] loadNibNamed:#"CellTest2" owner:self options:nil];
cell = mealPlanCell;*/
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
//self.mealPlanCell = nil;
}
cell.detailTextLabel.text = #"Test";
It will let me set the cell.textLabel.text to a value but not the detail one.
I figured out the reason if you leave
if(cell == nil){...}
around the cell = [[[UITableViewCell alloc]...
then the cells will not re render and thus will not update the style and or details so if you remove the if() then this will allow you to re render each cell in the table view if you are changing style back and forth. This is not a good thing to remove though if you think about it cause then it is going to low the tables "speed" which probably wont be noticeable but it is something to consider looking into as a possible issue. This is not what I did to solve the problem personally cause I choose to take a different approach but it is something that worked when I tried.
I had same problem: UITableViewCell initWithStyle:UITableViewCellStyleSubtitle is not working
For those that search and find this question... and have same problem as me, where you are using a prototype cell and the style is not defined correctly in the storyboard.
If your rowHeight is not tall enough, the cell.detailTextLabel.text won't be visible even if the cell.textLabel.text is visible. A rowHeight of 22 seems to be the minimum with the default font.