First of all sorry for asking this as I know there are a lot of questions which are similar to this. But so far nothing has worked for me. I have a table view with two buttons. On click of the button it loads two different custom cells. But I can't seem to clear out the old cell values no matter what I try. I have tried the prepareForReuse method to clear the old views but I end up with nothing displaying on the cells.
Here is the code that I am using.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if([[self.sections objectAtIndex:indexPath.section] count] > 0)
{
id object = [[self.sections objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
if (indexPath.section == self.sections.count-1)
{
if(self.CategoryButtonType == 0)
{
MediaListCarousel * cell = [self getMediaCellCarousel:object];
return cell;
}
else
{
NonMediaTableViewCell * cell = [self getNonMediaCell:object];
return cell;
}
}
else
{
//Do other stuff
}
}
return nil;
}
Here are the custom cells
-(NonMediaTableViewCell *)getNonMediaCell:(NSString *)name
{
NonMediaTableViewCell * cell = [self.tableView dequeueReusableCellWithIdentifier:nonmediaCellIdentifier];
if (cell == nil) {
cell = (NonMediaTableViewCell*)[VFHelper findCellWithClassName:[NonMediaTableViewCell class] nibName:#"NonMediaTableViewCell"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
[cell setNonMediaWithPackageName:name
delegate:self];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
return cell;
}
-(MediaListCarousel *)getMediaCellCarousel:(NSString *)name
{
MediaListCarousel * cell = [self.tableView dequeueReusableCellWithIdentifier:mediaCellIdentifier];
if (cell == nil) {
cell = (MediaListCarousel*)[VFHelper findCellWithClassName:[MediaListCarousel class] nibName:#"MediaListCarousel"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
[cell setUp:name delegate:self];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
return cell;
}
each of those custom cell has the prepareForReuse method as defined below.
- (void)prepareForReuse {
[super prepareForReuse];
// Clear contentView
BOOL hasContentView = [self.subviews containsObject:self.contentView];
if (hasContentView) {
for(UIView *subview in [self.contentView subviews])
{
[subview removeFromSuperview];
}
}
}
What happening when i add the removeFromSuperview in the prepareForReuse method I can empty view when I switch between the two views. If i dont use the prepareForReuse to remove the view I end up with views on top of each other when I click the different button. Can some one please help with this. Thanks in advance.
EDIT TO SHOW CUSTOM CELL CODE
-(void) getNonMediaCell:(NSString *)package
delegate:(NSObject <nonMediaCellDelegate> *)delegate
{
self.package = package;
[self loadValuefFromDB];
self.addonName = addonName;
_delegate = delegate;
[self.btnSeemore addTarget:self action:#selector(btnSeemoreClicked) forControlEvents:UIControlEventTouchUpInside];
if(_addons.isHidden)
{
_planDescTextView.hidden = YES;
_heightConstraintforPlanDescView.constant = 0;
_btnSeemore.imageView.transform = CGAffineTransformIdentity;
}
else
{
_planDescTextView.text = description;
CGSize neededSize = [_planDescTextView sizeThatFits:CGSizeMake(_planDescTextView.frame.size.width, CGFLOAT_MAX)];
_planDescTextView.hidden = NO;
_heightConstraintforPlanDescView.constant = neededSize.height + 5;
_btnSeemore.imageView.transform = CGAffineTransformMakeRotation(M_PI);
_btnSeemore.imageView.clipsToBounds = NO;
_btnSeemore.imageView.contentMode = UIViewContentModeCenter;
}
if(IsEmpty(addons.state))
{
_UIViewEntitlement.hidden = YES;
_UIViewBtnRepurchase.hidden = YES;
_seperatorView.hidden = YES;
[self resetCell];
[self setPriceLabelValue];
[self.purchaseBtn addTarget:self action:#selector(buttonClicked) forControlEvents:UIControlEventTouchUpInside];
self.purchaseBtn.accessibilityLabel = [NSString stringWithFormat:#"%#_Purcahse", addonName];
self.purchaseBtn.accessibilityValue = [NSString stringWithFormat:#"%#_Purcahse", addonName];
self.purchaseBtn.accessibilityIdentifier = [NSString stringWithFormat:#"%#_Purcahse", addonName];
self.recurringIndicatorImageView.hidden = NO;
[self addOnRecurringIndicatorImages];
}
else
{
_UIViewEntitlement.hidden = NO;
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, 20)];
VFAddonPlanentitlementCell * cell = (VFAddonPlanentitlementCell*)[VFHelper findCellWithClassName:[VFAddonPlanentitlementCell class] nibName:#"VFAddonPlanentitlementCell"];
[cell setFrame:CGRectMake(0, 0, self.frame.size.width, 20)];
if(!IsEmpty(_addons.remainingDays))
{
if(recurring || allowCancel)
{
if([[_addons.state uppercaseString] isEqualToString:#"ONHOLD"])
{
[cell setDaysRemainingColorWithTitleOnHold:#"Renews" daysRemainings:[_addons.remainingDays stringValue]];
}
else
{
[cell setRemainingColorWithTitle:#"Renews" daysRemainings:[_addons.remainingDays stringValue]];
}
}
else
{
[cell setDaysRemainingColorWithTitle:#"Time left" daysRemainings:[_addons.remainingDays stringValue]];
}
[headerView addSubview:cell];
}
[_UIViewEntitlement addSubview:headerView];
}
}
try this
-(void) getNonMediaCell:(NSString *)package
delegate:(NSObject <nonMediaCellDelegate> *)delegate
{
.....//other code
UIView *headerView = [_UIViewEntitlement viewWithTag:12345];
if(headerView == nil) {
headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, 20)];
[headerView setTag:12345];//set tag
} else {
NSLog(#"headerView already exist");
}
//set values
.....//other code
}
and in reuse method
- (void)prepareForReuse {
[super prepareForReuse];
UIView *header = [_UIViewEntitlement viewWithTag:12345];//use same tag
[header removeFromSuperview];
}
if you are creating and adding multiple views programatically, then set tag to each views and remove those in reuse by accessing it with same tag value.
Related
I have a method setting up value for table view for multi-selection row
- (id)initWithTitle:(NSString *)aTitle options:(NSArray *)aOptions matchingArray:(NSArray *)matchArray xy:(CGPoint)point size:(CGSize)size isMultiple:(BOOL)isMultiple
{
isMultipleSelection=isMultiple;
float height = MIN(size.height, DROPDOWNVIEW_HEADER_HEIGHT+[aOptions count]*44);
CGRect rect = CGRectMake(point.x, point.y, size.width, height);
if (self = [super initWithFrame:rect])
{
self.backgroundColor = [UIColor clearColor];
self.layer.shadowColor = [UIColor blackColor].CGColor;
self.layer.shadowOffset = CGSizeMake(2.5, 2.5);
self.layer.shadowRadius = 2.0f;
self.layer.shadowOpacity = 0.5f;
_kTitleText = [aTitle copy];
_kDropDownOption = #[#"India",#"Swaziland",#"Africa",#"Australlia",#"Pakistan",#"Srilanka",#"Mexico",#"United Kingdom",#"United States",#"Portugal"];
_kMatchingArray = #[#"United States",#"Swaziland"];
finalarray=[[NSMutableArray alloc]init];
for(int i = 0;i<[_kMatchingArray count];i++)
{
for(int j= 0;j<[_kDropDownOption count];j++)
{
if([[_kMatchingArray objectAtIndex:i] isEqualToString:[_kDropDownOption objectAtIndex:j]])
{
NSLog(#"%d",j);
NSString *str = [NSString stringWithFormat:#"%d",j];
[finalarray addObject:str];
}
else {
}
}
}
NSLog(#"finalArray:%#",finalarray);
// NSLog(#"%#",_kMatchingArray);
self.arryData=[[NSMutableArray alloc]init];
_kTableView = [[UITableView alloc] initWithFrame:CGRectMake(DROPDOWNVIEW_SCREENINSET,
DROPDOWNVIEW_SCREENINSET + DROPDOWNVIEW_HEADER_HEIGHT,
rect.size.width - 2 * DROPDOWNVIEW_SCREENINSET,
rect.size.height - 2 * DROPDOWNVIEW_SCREENINSET - DROPDOWNVIEW_HEADER_HEIGHT - RADIUS)];
_kTableView.separatorColor = [UIColor colorWithWhite:1 alpha:.2];
_kTableView.separatorInset = UIEdgeInsetsZero;
_kTableView.backgroundColor = [UIColor clearColor];
_kTableView.dataSource = self;
_kTableView.delegate = self;
[self addSubview:_kTableView];
if (isMultipleSelection) {
UIButton *btnDone=[UIButton buttonWithType:UIButtonTypeCustom];
[btnDone setFrame:CGRectMake(rect.origin.x+182,rect.origin.y-45, 82, 31)];
[btnDone setImage:[UIImage imageNamed:#"done#2x.png"] forState:UIControlStateNormal];
[btnDone addTarget:self action:#selector(Click_Done) forControlEvents: UIControlEventTouchUpInside];
[self addSubview:btnDone];
}
}
return self;
}
using this i have create a tableview fetching the values
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_kDropDownOption count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cel lForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentity = #"DropDownViewCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentity];
cell = [[DropDownViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentity];
NSInteger row = [indexPath row];
// NSIndexPath *selectedIndexPath = [finalarray addObject:indexPath.row];
UIImageView *imgarrow=[[UIImageView alloc]init ];
NSLog(#"aray:%#",self.arryData);
if([self.arryData containsObject:indexPath]){
imgarrow.frame=CGRectMake(230,2, 27, 27);
imgarrow.image=[UIImage imageNamed:#"check_mark#2x.png"];
} else
imgarrow.image=nil;
[cell addSubview:imgarrow];
cell.textLabel.text = [_kDropDownOption objectAtIndex:row] ;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if (isMultipleSelection) {
if([self.arryData containsObject:indexPath]){
[self.arryData removeObject:indexPath];
} else {
[self.arryData addObject:indexPath];
}
[tableView reloadData];
} else {
if (self.delegate && [self.delegate respondsToSelector:#selector(DropDownListView:didSelectedIndex:)]) {
[self.delegate DropDownListView:self didSelectedIndex:[indexPath row]];
}
// dismiss self
[self fadeOut];
}
}
I have two array one have total records of the tableview and another one have initially selected values.I have compare the two arrays and get matching indexpath. My problem was how to set check mark image on matched values row?
if ([_strProIDNS isEqualToString:strUNAssignNS])
{
tblViewCell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
tblViewCell.accessoryType = UITableViewCellAccessoryNone;
I am having two table views (table, table2) in scroll view. I want to scroll the table view left to right and right to left. in this below code 1st table view (table) appears, but when I swipe right to left 2nd table view (table2) is not appearing there. blank screen appears there. please help me in coding.
- (void)viewDidLoad
{
[super viewDidLoad];
UIScrollview * theScrollView=[[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
theScrollView.contentSize = CGSizeMake(320*2, self.theScrollView.frame.size.height);
theScrollView.delegate = self;
theScrollView.bounces = YES;
theScrollView.showsVerticalScrollIndicator = YES;
theScrollView.showsHorizontalScrollIndicator = YES;
[self.view addSubview:theScrollView];
UITableView * table = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) style:UITableViewStylePlain];
table.contentSize=CGSizeMake(320,200);
[table setDataSource:self];
[table setDataSource:self];
[table setDelegate:self];
[table setTranslatesAutoresizingMaskIntoConstraints: YES];
table.tag = 100;
[theScrollView addSubview:self.table];
UITableView * table2 = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) style:UITableViewStylePlain];
table2.contentSize=CGSizeMake(320,200);
[table2 setDataSource:self];
[table2 setDelegate:self];
table2.tag = 101;
[theScrollView addSubview:self.table2];
}
- (void)viewDidUnload
{
[super viewDidUnload];
self.theScrollView = nil;
self.table = nil;
self.table2 = nil;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (tableView.tag == 100) {
return 3;
}
if (tableView.tag == 101) {
return 4;
}
return 0;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView.tag == 100) {
return 5;
}
if (tableView.tag == 101) {
return 5;
}
return 0;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if (tableView.tag == 100) {
return [NSString stringWithFormat:#"%#", #"Plain"];
}
if (tableView.tag == 101) {
return [NSString stringWithFormat:#"%#", #"Group"];
}
return nil;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView.tag == 100) {
static NSString *cellIdentifier1 = #"cellIdentifier1";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier1];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier1] ;
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
}
cell.textLabel.text = #"45";
return cell;
}
if (tableView.tag == 101) {
static NSString *cellIdentifier2 = #"cellIdentifier2";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier2];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier2] ;
cell.selectionStyle = UITableViewCellSelectionStyleGray;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
cell.textLabel.text = #"45";;
return cell;
}
return nil;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
float x = scrollView.contentOffset.x;
if (x > 320/2 && x < 640/2) {
self.title = #"TableView Group";
}
if (x > 0 && x < 320/2) {
self.title = #"TableView Plain";
[self.table reloadData];
}
}
According to your code, you setting equal frame for both table views:
CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)
So by adding them to scroll view, you just placing them on top of each other.
Try to change the frame for second table view:
CGRectMake(320, 0, self.view.frame.size.width, self.view.frame.size.height)
UISegmentedControl changes tableView datasource.
After I described [myView addSubview:_tableView];
instead of [self.view addSubview:_tableView];,
daySegmentedControl process stopped working.
I have this code.
ViewController.m
#implementation ViewController
{
int _tableType;
NSArray *_data1;
NSArray *_data2;
}
#synthesize segment;
#synthesize daySegment;
#synthesize myView;
- (void)viewDidLoad
{
[super viewDidLoad];
_tableType = 1;
_data1 = #[#[#"A",#"B",#"C"]];
_data2 = #[#[#"D",#"E",#"F"]];
myView = [[UIView alloc]initWithFrame:CGRectMake(-1, 44, 340, 480)];
[self.view addSubview:myView];
myView.opaque = NO;
myView.backgroundColor = [UIColor colorWithWhite:1.0f alpha:0.0f];
[self.view bringSubviewToFront:myView];
[self segmentView];
[self daySegmentView];
[self dayTableView];
}
- (void)segmentView
{
NSArray *SegmentContent = [NSArray arrayWithObjects:#"View1",#"View2",nil];
segment = [[UISegmentedControl alloc] initWithItems:WDSegmentContent];
segment.frame = CGRectMake(-2, 20, 326, 25);
segment.selectedSegmentIndex = 0;
[segment addTarget:self action:#selector(WDSegmentAction:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview:segment];
}
- (void)WDSegmentAction:(id)sender
{
switch (segment.selectedSegmentIndex){
case 0:
[self dayTableView];
break;
case 1:
[self dayTableView];
break;
default:
break;
}
}
- (void)daySegmentView
{
NSArray *daySegmentContent = [NSArray arrayWithObjects:#"A",#"D",nil];
daySegment = [[UISegmentedControl alloc] initWithItems:daySegmentContent];
daySegment.frame = CGRectMake(0, 0, 326, 25);
daySegment.selectedSegmentIndex = 0;
[daySegment addTarget:self action:#selector(daySegmentAction:) forControlEvents:UIControlEventValueChanged];
[myView addSubview:daySegment];
}
- (void)daySegmentAction:(id)sender
{
switch (segment.selectedSegmentIndex){
case 0:
_tableType = 1;
[self.tableView reloadData];
break;
case 1:
_tableType = 2;
[self.tableView reloadData];
break;
default:
break;
}
}
- (void)dayTableView
{
_tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 30, 320, 480)];
_tableView.dataSource = self;
_tableView.delegate = self;
[myView addSubview:_tableView];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_data1[section]count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSString *data;
if (_tableType == 1) {
data = _data1[indexPath.section][indexPath.row];
} else if (_tableType == 2){
data = _data2[indexPath.section][indexPath.row];
}
cell.textLabel.text = data;
return cell;
}
#end
Any idea on how I could fix it?
I used different approach for changing segments. Just for illustration:
in segment changed method:
[_tableView reloadData];
In your numberOfRowsInSection:
if(_segControl.selectedSegmentIndex == 0)
{
return [dataSourceOne count];
}else
{
return [dataSourceTwo count];
}
}
In your heightForRowAtIndexPath
if(_segControl.selectedSegmentIndex == 0) { //one
return 60;
} else { //two
return 70;
}
In your cellForRowAtIndexPath
if(_segControl.selectedSegmentIndex == 0) {
//generate and populate cell for type one
}else
{
//generate and populate cell for type two
}
Use daySegment.selectedSegmentIndex instead of segment.selectedSegmentIndex in
- (void)daySegmentAction:(id)sender
In landscape view I have a UIScrollView where I add UITableViews dynamically. UITableViews are 200px wide so there are can be 2-3 of them on the screen. Each cell has a button.
When the button is pushed how can I know which UITableView that button belong to?
PS implementation of cellForRowAtIndexPath:
cell = (CellHistory*)[tableView dequeueReusableCellWithIdentifier:#"Cell"];
if(!cell)
{
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"CellHistory" owner:nil options:nil];
for(id currentObject in topLevelObjects)
{
if([currentObject isKindOfClass:[CellHistory class]])
{
cell = (CellHistory *)currentObject;
break;
}
}
}
UIButton *noteButton = [UIButton buttonWithType:UIButtonTypeCustom];
[noteButton setFrame:CGRectMake(0, 0, 44, 44)];
[cell addSubview:noteButton];
[noteButton addTarget:self action:#selector(checkButtonTapped:event:) forControlEvents:UIControlEventTouchUpInside];
return cell;
PS2 how I add UITableViews to UIScrollView:
for (int i=0; i<allDays.count; i++) {
CGRect landTableRect = CGRectMake(landContentOffset+0.0f, 60.0f, 200.0f, 307.0f);
landTableView = [[UITableView alloc] initWithFrame:landTableRect style:UITableViewStylePlain];
[landTableView setTag:i];
[landTableView setNeedsDisplay];
[landTableView setNeedsLayout];
landTableView.delegate = self;
landTableView.dataSource = self;
[_landScrollView addSubview:landTableView];
[landTableView reloadData];
landContentOffset += landTableView.frame.size.width;
_landScrollView.contentSize = CGSizeMake(landContentOffset, _landScrollView.frame.size.height);
[allLandTableViews addObject:landTableView];
}
You should add a tag to each button that matches the tag for each table view. Then you can compare them
In your cellForRowAtIndexPath: check
if (tableView == youTableViewA)
button.tag = 1;
else if (tableView == yourTableViewB)
button.tag = 2;
.
.
.
And so on.
Where you are assigning a target to your button with addTarget:action:forControlEvents: make sure your target method accepts a parameter:
- (void) targetMethod:(id)sender{
if (sender.tag == 1){
//tableViewA
}else if (sender.tag == 2){
//tableViewB
}
}
.
.
.
and so on.
You can use a helpful category method on UIView to just walk your view hierarchy until a matching parent is discovered:
#implementation UIView (ParentOfClass)
- (UIView *)parentViewWithClass:(Class)aClass
{
UIView *current = self;
UIView *result = nil;
while ((current = current.superview) != nil) {
if ([current isKindOfClass:aClass]) {
result = current;
break;
}
}
return result;
}
#end
Then in your UIButton handling code you get the UITableView by a simple call:
- (IBAction)pressedButton:(id)sender
{
UITableView *tableView = [sender parentViewWithClass:[UITableView class]];
// ...
}
I am trying to dynamically resize some UITableViewCell's based on the height of UITextView's contained within them.
There's loads of solutions to this by keeping a pointer to the UITextView and getting it's content size in heightForRowAtIndexPath however when the whole table is created dynamically with an unknown number of rows and an unknown number of them rows contain UITextView's this just isn't possible.
It would be easy if I could call the cell in question during heightForRowAtIndexPath but that causes an infinite loop and crash as this method is called before any cell's are even created.
Any other solutions?
I am using a UITableViewCell subclass for my cell like this:
- (void)initalizeInputView {
// Initialization code
self.selectionStyle = UITableViewCellSelectionStyleNone;
self.textView = [[UITextView alloc] initWithFrame:CGRectZero];
self.textView.autocorrectionType = UITextAutocorrectionTypeDefault;
self.textView.autocapitalizationType = UITextAutocapitalizationTypeNone;
self.textView.textAlignment = NSTextAlignmentRight;
self.textView.textColor = [UIColor lightBlueColor];
self.textView.font = [UIFont fontWithName:#"HelveticaNeue-Light" size:17];
self.textView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
self.textView.keyboardType = UIKeyboardTypeDefault;
[self addSubview:self.textView];
self.textView.delegate = self;
}
- (BOOL)resignFirstResponder {
if (_delegate && [_delegate respondsToSelector:#selector(tableViewCell:didEndEditingWithLongString:)]) {
[_delegate tableViewCell:self didEndEditingWithLongString:self.stringValue];
}
return [super resignFirstResponder];
}
- (void)setKeyboardType:(UIKeyboardType)keyboardType
{
self.textView.keyboardType = keyboardType;
}
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
[self initalizeInputView];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self initalizeInputView];
}
return self;
}
- (void)setSelected:(BOOL)selected {
[super setSelected:selected];
if (selected) {
[self.textView becomeFirstResponder];
}
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
if (selected) {
[self.textView becomeFirstResponder];
}
}
- (void)setStringValue:(NSString *)value {
self.textView.text = value;
}
- (NSString *)stringValue {
return self.textView.text;
}
- (void)textViewDidBeginEditing:(UITextView *)textView
{
// For keyboard scroll
UITableView *tableView = (UITableView *)self.superview;
AppSetupViewController *parent = (AppSetupViewController *)_delegate;
parent.activeCellIndexPath = [tableView indexPathForCell:self];
}
- (void)textViewDidChange:(UITextView *)textView
{
if (textView.contentSize.height > contentRowHeight) {
contentRowHeight = textView.contentSize.height;
UITableView *tableView = (UITableView *)self.superview;
[tableView beginUpdates];
[tableView endUpdates];
[textView setFrame:CGRectMake(0, 0, 300.0, textView.contentSize.height)];
}
}
- (void)textViewDidEndEditing:(UITextView *)textView
{
if (_delegate && [_delegate respondsToSelector:#selector(tableViewCell:didEndEditingWithLongString:)]) {
[_delegate tableViewCell:self didEndEditingWithLongString:self.stringValue];
}
UITableView *tableView = (UITableView *)self.superview;
[tableView deselectRowAtIndexPath:[tableView indexPathForCell:self] animated:YES];
}
- (void)layoutSubviews {
[super layoutSubviews];
CGRect editFrame = CGRectInset(self.contentView.frame, 10, 10);
if (self.textLabel.text && [self.textLabel.text length] != 0) {
CGSize textSize = [self.textLabel sizeThatFits:CGSizeZero];
editFrame.origin.x += textSize.width + 10;
editFrame.size.width -= textSize.width + 10;
self.textView.textAlignment = NSTextAlignmentRight;
} else {
self.textView.textAlignment = NSTextAlignmentLeft;
}
self.textView.frame = editFrame;
}
Which is created in cellForRowAtIndexPath like this:
else if ([paramType isEqualToString:#"longString"]) {
MyIdentifier = #"AppActionLongString";
LongStringInputTableViewCell *cell = (LongStringInputTableViewCell *)[tableView dequeueReusableCellWithIdentifier:MyIdentifier];
cell.textLabel.text = [[[_selectedAction objectForKey:#"parameters"] objectAtIndex:indexPath.row] objectForKey:#"name"];
cell.params = [[_selectedAction objectForKey:#"parameters"] objectAtIndex:indexPath.row];
cell.textView.text = [results objectAtIndex:indexPath.row];
return cell;
}
Simply passing back the height to a variable in my ViewController is no good because like I said, there could be several of these cells within the table.
Thanks
Use this method to dynamically resize your tableviewCell. First store the user input in NSMutable Array and after that reload table. Hope it will help you.
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *msg =[self.messages objectAtIndex:indexPath.row];
CGSize textSize = { 120, 10000.0 };
CGSize size = [msg sizeWithFont:[UIFont systemFontOfSize:15]
constrainedToSize:textSize
lineBreakMode:UILineBreakModeWordWrap];
return size.height+20;
}
I needed a dynamic table view cell height based on the amount of text to be displayed in that cell. I solved it in this way:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (!isLoading)
{
if ([self.conditionsDataArray count]>0)
{
Conditions *condition =[self.conditionsDataArray objectAtIndex:indexPath.row];
int height;
UITextView *textview = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, 236, 0)]; //you can set your frame according to your need
textview.text = condition.comment;
textview.autoresizingMask = UIViewAutoresizingFlexibleHeight;
[tableView addSubview:textview];
textview.hidden = YES;
height = textview.contentSize.height;
NSLog(#"TEXT VIEW HEIGHT %f", textview.contentSize.height);
[textview removeFromSuperview];
[textview release];
return height;
}
return 55; //Default height, if data is in loading state
}
Notice that the Text View has been added as Subview and then made hidden, so make sure you add it as SubView otherwise it's height will not be considered.
It would be easy if I could call the cell in question during heightForRowAtIndexPath but that causes an infinite loop and crash as this method is called before any cell's are even created. Any other solutions?
You can. I would guess you're attempting to call cellForRowAtIndexPath, which will cause an infinite loop. But you should rather be dequeuing the cell directly by calling dequeueReusableCellWithIdentifier.
See the table view delegate implementation of TLIndexPathTools. The heightForRowAtIndexPath method looks like this:
(EDIT Initially forgot to include the method prototypeForCellIdentifier that actually dequeues the cell.)
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
id item = [self.dataModel itemAtIndexPath:indexPath];
NSString *cellId = [self cellIdentifierAtIndexPath:indexPath];
if (cellId) {
UITableViewCell *cell = [self prototypeForCellIdentifier:cellId];
if ([cell conformsToProtocol:#protocol(TLDynamicSizeView)]) {
id<TLDynamicSizeView> v = (id<TLDynamicSizeView>)cell;
id data;
if ([item isKindOfClass:[TLIndexPathItem class]]) {
TLIndexPathItem *i = (TLIndexPathItem *)item;
data = i.data;
} else {
data = item;
}
CGSize computedSize = [v sizeWithData:data];
return computedSize.height;
} else {
return cell.bounds.size.height;
}
}
return 44.0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView prototypeForCellIdentifier:(NSString *)cellIdentifier
{
UITableViewCell *cell;
if (cellIdentifier) {
cell = [self.prototypeCells objectForKey:cellIdentifier];
if (!cell) {
if (!self.prototypeCells) {
self.prototypeCells = [[NSMutableDictionary alloc] init];
}
cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
//TODO this will fail if multiple tables are being used and they have
//overlapping identifiers. The key needs to be unique to the table
[self.prototypeCells setObject:cell forKey:cellIdentifier];
}
}
return cell;
}
This uses a protocol TLDynamicSizeView that any cell can implement to have it's height calculated automatically. Here is a working example project. The cell's implementation of the protocol looks like this:
#implementation DynamicHeightCell
- (void)awakeFromNib
{
[super awakeFromNib];
self.originalSize = self.bounds.size;
self.originalLabelSize = self.label.bounds.size;
}
- (void)configureWithText:(NSString *)text
{
self.label.text = text;
[self.label sizeToFit];
}
#pragma mark - TLDynamicSizeView
- (CGSize)sizeWithData:(id)data
{
[self configureWithText:data];
//the dynamic size is calculated by taking the original size and incrementing
//by the change in the label's size after configuring
CGSize labelSize = self.label.bounds.size;
CGSize size = self.originalSize;
size.width += labelSize.width - self.originalLabelSize.width;
size.height += labelSize.height - self.originalLabelSize.height;
return size;
}
#end
just comment
if (cell == nil)
Hope, this will help you.