uItableviewcell to retrieve value dynamically - iphone

i did an application which has imageview to capture image from camera and a button where button is clicked pickerView will appear by actionsheet and will choose type of image(jpg, png, bmp..), once select from picker, button title will change according to the pickerView result,
then i try to convert this to UITableView, which has 2 section ( 1 for image and 1 for select the type of the image,
now i'm having problem where i try to imageView into the cell but image was overlapping other cell, and once image capture from camera that imageView not updated but once scroll the table than only updated,
another problem is, once select 2nd section i able to call the pickerView to choose the image type as previously, but once select from pickerView i don't how to updated the cell.text
below is my code, can anyone help here or improve it,
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
switch (section) {
case 0:
return NSLocalizedString(#"Image", #"");
break;
case 1:
return NSLocalizedString(#"Image type", #"");
break;
default:
break;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"] autorelease];
}
switch (indexPath.section) {
case 0:
{
UIImageView *abc = [[UIImageView alloc] initWithFrame:CGRectMake(5,5,100,100)];
abc.image = imageView.image;
[cell addSubview:abc];
}
break;
case 1:
cell.textLabel.text = #"- Click here -";
break;
default:
break;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:#"Cell"] autorelease];
}
if(indexPath.section == 0) {
NSLog(#"selected %d",indexPath.section);
}
if(indexPath.section == 1) {
NSLog(#"selected %d",indexPath.section);
[self chooseType];
}
}
- (void)chooseType{
actionSheet = [[UIActionSheet alloc] initWithTitle:#""
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
NSArray *typeObject = [NSArray arrayWithObjects:#".jpg",#".png",#".bmp",nil];
self.pickerData = typeObject;
pickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0.0, 44.0, 0.0, 0.0)];
pickerView.delegate = self;
pickerView.showsSelectionIndicator = YES;
pickerDateToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
pickerDateToolbar.barStyle = UIBarStyleBlackOpaque;
[pickerDateToolbar sizeToFit];
NSMutableArray *barItems = [[NSMutableArray alloc] init];
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
[barItems addObject:flexSpace];
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(TypeDonePick)];
[barItems addObject:doneBtn];
[pickerDateToolbar setItems:barItems animated:YES];
[actionSheet addSubview:pickerDateToolbar];
[actionSheet addSubview:pickerView];
[actionSheet showInView:self.view];
[actionSheet setBounds:CGRectMake(0,0,320, 464)];
[pickerView release];
[actionSheet release];
}
- (void)TypeDonePick
{
NSInteger row = [pickerView selectedRowInComponent:0];
titleCause.textColor = [UIColor blackColor];
titleCause.text = [pickerData objectAtIndex:row];
NSLog(#" %# ",titleCause.text);
[actionSheet dismissWithClickedButtonIndex:0 animated:YES];
}
is it possible to change cell test from outside range UITable function
thanks

Your problem is that the table doesn't know it needs to update the cells already visible. for a quick solution just add [tableView reloadData] after the user picks the image/image type, this will cause the table to recreate the cells and get the updated data from them.
If you want to update cells individually you can use [tableView cellForRowAtIndexPath:] to get the cell you want to update. e.g.
UITableViewCell *cell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:1]];
cell.textLabel.text = #"updated text";
// You might need to call the following function though I'm not sure
// [cell.textLabel setNeedsDisplay];
If you want to update the image I suggest you add a tag to the imageView in the cell and then you'll be able to change it as follows:
UITableViewCell *cell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
UIImageView *imageView = [cell viewWithTag:kImageViewTag];
imageView.image = updatedImage;
// Again you might need to tell the image to refresh it self
//[imageView setNeedsDisplay];

To change the LabelText of UITableViewCell at IndexPath, We can use the code below.
--> It works correctly!
(with this example, I change labelText at row 0 of tableView):
UITableViewCell *cell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
cell.textLabel.text = #"updated text";
// must to write line below to update labelText for row 0
[tableView setNeedsDisplay];

Related

Objective-C: How to retain inputs and also tag names when UItextFields scrolled off?

My App is placing questions and according to the question, placing either UITextField or UISwitch.
When a user input texts it automatically detects which textField and placing the texts accordingly.
It works well but when the items are scrolled off, it removes the user inputs and tag names as well, and when displayes the area placing a new items on top of that.
So when a user input texts it stores it into the old textField.
I would like to know how to prevent it from this issue.
Is there any suggestion? Thanks in advance.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
NSLog(#"-------------cellForRowAtIndexPath---------------");
cell_id = [qid objectAtIndex:[indexPath row] ];
static NSString *CellIdentifier = #"Cell";
label = nil;
cell = (UITableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
[self configureLabel];
[[cell contentView] addSubview:label];
}
dict = [qtext objectAtIndex:[indexPath row]];
celltext = [NSString stringWithFormat:#"%#\n\n\n",[[dict allKeys] objectAtIndex:0]];
dict = [qtype objectAtIndex:[indexPath row]];
type = [[dict allKeys] objectAtIndex:0];
//place the question
cell.textLabel.text = celltext;
NSLog(#"celltext=%#",celltext);
if([type isEqualToString:#"devider"]){
[self configureDevider];
}else{
[self configureCell];
}
if([cell_id intValue] == ([qid count])){
tabledone = #"Yes";
}
tableView.backgroundColor=[UIColor clearColor];
tableView.opaque=NO;
tableView.backgroundView=nil;
NSString *a = [arrAllheight objectAtIndex:[indexPath row]];
allheight +=thisheight;
thisheight =[a intValue];
if([type isEqualToString:#"YN"]){
DCRoundSwitch *ynSwitch = [[DCRoundSwitch alloc] initWithFrame:CGRectMake(220,thisheight-40,80,27)] ;
ynSwitch.onText=#"Yes";
ynSwitch.offText=#"No";
[answers addObject:ynSwitch];
[cell addSubview:ynSwitch];
[ynSwitch setTag:[cell_id intValue]];
[ynSwitch addTarget:self action:#selector(setAnswersForRoundSwitches:) forControlEvents:UIControlEventValueChanged];
i++;
}else if([type isEqualToString:#"freetext"]){
//When the done button was clicked, remove the keybords from the screen
[self makeTextField];
[rtxtfield addTarget:self action:#selector(setAnswersfortextFields:) forControlEvents:UIControlEventEditingDidEndOnExit];
// [rtxtfield value];
}else if([type isEqualToString:#"dropdown"]){
picc = [picker_array objectForKey:[[NSString alloc] initWithFormat:#"%d",cell_id]];
//Choose an array for this textField
// [self getPickerArray];
[self makeTextField];
//[rtxtfield addTarget:self action:#selector(setAnswersfortextFields:) forControlEvents:UIControlEventEditingDidEndOnExit];
//When the done button was clicked, remove the keybords from the screen
[rtxtfield addTarget:self action:#selector(textFieldReturn:) forControlEvents:UIControlEventEditingDidEndOnExit];
//Get the tag for picker
[rtxtfield addTarget:self action:#selector(getTag:) forControlEvents:UIControlEventTouchDown];
//Display picker
[rtxtfield addTarget:self action:#selector(acsheet:) forControlEvents:UIControlEventTouchDown];
//set Tag for the textField
[rtxtfield setTag:[cell_id intValue]];
NSLog(#"rtxtfield tag=%d",rtxtfield.tag);
}
if([type isEqualToString:#"devider"]){
[self caliculateHeightofCell];
}else{
[self caliculateHeightofCell];
}
return cell;
}
Save the state of your controls in your data model as soon as they change. So, maybe your model is an array of questions, and each question has an instance variable that can hold the answer. Your view controller is probably both the table data source and table delegate, and you should make it the target of any controls in the cells, too. That is, when you set up a new cell in your -tableView:cellForRowAtIndexPath:, make the view controller the target of the UITextField or UISwitch in the cell. When the user changes either of those controls, then, the change will trigger an action in the view controller, and the view controller can retrieve the new value of the control and store it in the corresponding question in the data model.
If you take this approach, you never have to worry about questions scrolling out of view. As soon as the question scrolls back into view, -tableView:cellForRowAtIndexPath: will be called for that row again, and you'll have all the information you need to reconstitute that cell.
Save the text to the dataSource. UITableViewCells must not contain any state information.
Implement something similar to this:
- (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];
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(2, 2, 200, 40)];
textField.tag = 999;
textField.delegate = self;
textField.placeholder = #"Enter text here";
[cell.contentView addSubview:textField];
}
UITextField *textField = (UITextField *)[cell.contentView viewWithTag:999];
textField.text = [self.dataSource objectAtIndex:indexPath.row];
/* configure cell */
return cell;
}
- (void)textFieldDidEndEditing:(UITextField *)textField {
UIView *contentView = [textField superview];
UITableViewCell *cell = (UITableViewCell *)[contentView superview];
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
[self.dataSource replaceObjectAtIndex:indexPath.row withObject:textField.text];
}
Do not add views outside of if (cell == nil)!
If you have different type of cells use a different CellIdentifier! Like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *SwitchCellIdentifier = #"SwitchCell";
static NSString *TextFieldCellIdentifier = #"TextFieldCell";
UITableViewCell *cell = nil;
if (/* current cell is a text field cell */) {
cell = [tableView dequeueReusableCellWithIdentifier:TextFieldCellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TextFieldCellIdentifier];
// add textField
}
// configure cell...
}
else if (/* current cell is a switch cell */) {
cell = [tableView dequeueReusableCellWithIdentifier:SwitchCellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SwitchCellIdentifier];
// add switch
}
// configure cell...
}
return cell;
}
I took a day to fix the problem, but I've finally got it right:
Sorry it's a long code cause it's using textField, DCRoundSwitch, and pickerView.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"-----------------cellForRowAtIndexPath---------------");
Questions *q = [qtext objectAtIndex:indexPath.row];
NSLog(#"question=%#",q.question);
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
static NSString *SwitchCellIdentifier = #"SwitchCell";
static NSString *TextFieldCellIdentifier = #"TextFieldCell";
static NSString *DropDownFieldCellIdentifier = #"DropDownCell";
cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:TextFieldCellIdentifier];
if ([q.question_type isEqualToString:#"freetext"]) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TextFieldCellIdentifier];
if (cell == nil) {
[self makeTextField];
[cell.contentView addSubview:rtxtfield];
cell.textLabel.text = q.question;
}
[self makeTextField];
[self configureCell];
[self configureLabel];
cell.textLabel.text = q.question;
[cell.contentView addSubview:rtxtfield];
rtxtfield.text = [appDelegate.dataSource objectAtIndex:indexPath.row];
rtxtfield.tag=[indexPath row];
}else if([q.question_type isEqualToString:#"YN"]){
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SwitchCellIdentifier];
if (cell == nil) {
[self makeDCRoundSwitch];
[ynSwitch setTag:[indexPath row]];
cell.textLabel.text = q.question;
[self configureLabel];
[self configureCell];
}
[self makeDCRoundSwitch];
[ynSwitch setTag:[indexPath row]];
cell.textLabel.text = q.question;
[self configureLabel];
[self configureCell];
[ynSwitch addTarget:self action:#selector(ynSwitchDidEndEditing:) forControlEvents:UIControlEventValueChanged];
if([[appDelegate.dataSource objectAtIndex:indexPath.row] isEqualToString:#"Yes"]){
[ynSwitch setOn:YES animated:YES];
} else{
[ynSwitch setOn:NO animated:YES];
}
rtxtfield.tag=[indexPath row];
} else if([q.question_type isEqualToString:#"dropdown"]){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:DropDownFieldCellIdentifier];
if (cell == nil) {
[self makeTextField];
[cell.contentView addSubview:rtxtfield];
cell.textLabel.text = q.question;
}
[self makeTextField];
[self configureCell];
[self configureLabel];
cell.textLabel.text = q.question;
[cell.contentView addSubview:rtxtfield];
picc=q.question_array;
//When the done button was clicked, remove the keybords from the screen
[rtxtfield addTarget:self action:#selector(textFieldReturn:) forControlEvents:UIControlEventEditingDidEndOnExit];
//Get the tag for picker
[rtxtfield addTarget:self action:#selector(getTag:) forControlEvents:UIControlEventTouchDown];
//Display picker
[rtxtfield addTarget:self action:#selector(acsheet:) forControlEvents:UIControlEventTouchDown];
//set Tag for the textField
[rtxtfield setTag:[indexPath row]];
// AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
rtxtfield.text = [appDelegate.dataSource objectAtIndex:indexPath.row];
rtxtfield.tag=[indexPath row];
}
[self makeTextField];
rtxtfield.tag=[indexPath row];
tableView.backgroundColor=[UIColor clearColor];
tableView.opaque=NO;
tableView.backgroundView=nil;
return cell;
}
try this
label = nil;
//cell = (UITableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
[self configureLabel];
[[cell contentView] addSubview:label];
//}
comment your code like that and tell me what happens

Adding a UITextField to a UITableViewCell only shows a textField in the LAST cell

I have a table view that has many cells. Each cell has its own UITextField. I added the text fields programmatically. I want each and every textField to appear when the edit button is hit. (now table is in edit mode) and when pressed again, i want all of the textFields to vanish(leaving the edit mode). I know that i can accomplish this using the hidden property, but i tried doing this in this method:
- (IBAction)editButton:(id)sender
{
if (self.editing)
{
[self setEditing:NO animated:YES];
[self.myTableView setEditing:NO animated:YES];
EditButton.title = #"Edit";
cellText.hidden = YES; //<-- THIS IS THE CODE
}
else
{
[self setEditing:YES animated:YES];
[self.myTableView setEditing:YES animated:YES];
EditButton.title = #"Done";
cellText.hidden = NO; //<-- THIS IS THE CODE
}
}
but it only shows and hides the VERY LAST cell's textField. How can i get it to where it shows and then doesnt show EVERY cell's textFIeld? Many thanks in advance!!!
CELL FOR ROW
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cellText = [[UITextField alloc]init];
[cellText setFrame:CGRectMake(190, 15, 55, 30)];
cellText.text = #"1";
cellText.borderStyle = UITextBorderStyleRoundedRect;
cellText.hidden = YES;
cellText.userInteractionEnabled = NO;
[cell addSubview:cellText];
}
return cell;
}
Thanks in advance!! :D
You can get rid of this issue, using this trick, I am not sure as if it would create the memory leak within your code.Since, it create new cell each time.But surely you can use it,if you don't get some proper way of doing it. ;)
- (IBAction)editButton:(id)sender
{
if (self.editing)
{
[self setEditing:NO animated:YES];
[self.myTableView setEditing:NO animated:YES];
EditButton.title = #"Edit";
}
else
{
[self setEditing:YES animated:YES];
[self.myTableView setEditing:YES animated:YES];
EditButton.title = #"Done";
}
[self.myTableView reloadData];
}
After reloading the TableView, check the condition in cellForRowAtIndexPath, either pass the value of self.editing to TextField which makes it hide/show.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cellText = [[UITextField alloc]init];
[cellText setFrame:CGRectMake(190, 15, 55, 30)];
cellText.text = #"1";
cellText.borderStyle = UITextBorderStyleRoundedRect;
cellText.hidden = YES;
cellText.backgroundColor = [UIColor redColor];
cellText.userInteractionEnabled = NO;
[cell addSubview:cellText];
cellText.hidden=!self.editing;
return cell;
}
Although you create a text field for each cell, you keep a reference only to the last one in the ivar named cellText. That's why you show/hide the only text field.
I suggest you reload the table when toggling the editing mode, and set the text fields visibility in tableView:cellForRowAtIndexPath:.
Oh, and you should release cellText after adding it as a subview. Otherwise you are leaking memory. And it is highly recommended that you add subviews to UITableViewCell content view, rather than directly to the cell.
Try this code
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (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] autorelease];
}
UITextField * cellText = [[UITextField alloc] initWithFrame:CGRectMake(1, 1, 100, 30)];
cellText.tag = 1;
cellText.textColor = [UIColor darkTextColor];
//cellText.numberOfLines = 0;
cellText.font = [ UIFont fontWithName: #"Helvetica-Bold" size: 12.0 ] ;
cellText.backgroundColor = [ UIColor clearColor ] ;
cellText.text = #"123";
cellText.hidden = YES;
[cell.contentView addSubview:cellText];
[cellText release];
cellText =nil;
// Set up the cell...
return cell;
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)aTableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
// Detemine if it's in editing mode
UITextField *cellText = (UITextField *)[[aTableView cellForRowAtIndexPath:indexPath] viewWithTag:1];
if (!self.editing)
{
[self setEditing:NO animated:YES];
[self.tableView setEditing:NO animated:YES];
// EditButton.title = #"Edit";
cellText.hidden = YES; //<-- THIS IS THE CODE
}
else
{
[self setEditing:YES animated:YES];
[self.tableView setEditing:YES animated:YES];
// EditButton.title = #"Done";
cellText.hidden = NO; //<-- THIS IS THE CODE
}
return UITableViewCellEditingStyleNone;
}
hi friend this code is working fine for me, believe you too have a grate day
This is actually normal. Per the Apple documentation under addSubview:
Views can have only one superview. If view already has a superview and
that view is not the receiver, this method removes the previous
superview before making the receiver its new superview.
So it will keep removing it adding and removing from cells until it gets to the last one.

Returning more cells in a UITableView

I am using MGTwitterEngine and have almost EVERYTHING figured out, but for some reason I cannot figure out how to return more tweets in my timeline! It receives around 20 tweets by the method I am using and if I add a integer for example: return count = 100;, I can tell I now have 100 cells when it loads and by the scroll indicator but when I scroll to that 18- 19 cell I get this error:
SIGABRT
-[NSMutableArray objectAtIndex:]: index 20 beyond bounds [0 .. 19]'
* Call stack at first throw:
I know what it means: theres no more information to receive at cell 20. I'm baffled and went in and out of MGTwitterEngine looking for a default tweet count but I can't find it. I am using the dump to create my NSStrings and the dump only seems to give around 20 tweets per login. Please help, any suggestions are good in my book! Thank you!
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
int count = [tweets count];
// Return just enough cells to fill the screen during loading ....
if (count == 0)
count = MyCustomRowCount;
else {
//Here is where I think I need to add a else return integer but dont know how
}
return count;
return [tweets count];
return [authors count];
return [avatarsURL count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *identifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
[cell autorelease];
}
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cell"]autorelease];
/*
//Here it adds a nice shadow to the table view but will crash on rotation and send a
wird dump !!!????
tableView.layer.shadowColor = [[UIColor blackColor] CGColor];
tableView.layer.shadowOffset = CGSizeMake(1.0f, 1.0f);
tableView.layer.shadowRadius = 8.0f;
tableView.layer.shadowOpacity = 1.0f;
*/
[cell.textLabel setNumberOfLines:1];
[cell.textLabel setText:[(Tweet*)[authors objectAtIndex:indexPath.row] author]];
[cell.detailTextLabel setText:[(Tweet*)[tweets objectAtIndex:indexPath.row] tweet]];
[cell.detailTextLabel setNumberOfLines:10];
[cell.textLabel setTextColor:[UIColor darkGrayColor]];
[cell.textLabel setShadowColor:[UIColor whiteColor]];
[cell.textLabel setShadowOffset:CGSizeMake(0.5, 0.5)];
[cell.detailTextLabel setTextColor:[UIColor blackColor]];
//[cell.detailTextLabel setText:[(Tweet*)[retweetCount objectAtIndex:indexPath.row]
reTweetCount]];
[cell.textLabel setUserInteractionEnabled:YES];
[cell.contentView setMultipleTouchEnabled:YES];
// cell.text = [[NSString alloc] initWithFormat:#"Cell :%i", indexPath.row];
// Here we use the new provided setImageWithURL: method to load the web image with
SDWebImageManager
[cell.imageView setImageWithURL:[NSURL URLWithString:[(Tweet*)[avatarsURL
objectAtIndex:indexPath.row]avatarURL]]
placeholderImage:[UIImage imageNamed:#"avatar.png"]];
//add gradient to cell
UIImage *gradient = [UIImage imageNamed:#"gradientcell2.png"];
UIImageView *cellimage = [[UIImageView alloc] initWithImage:gradient];
cellimage.contentMode = UIViewContentModeScaleToFill;
cell.backgroundView = cellimage;
[cellimage release];
UIImage *selectedGradient = [UIImage imageNamed:#"selectedcell.png"];
UIImageView *selectedCell = [[UIImageView alloc] initWithImage:selectedGradient];
selectedCell.contentMode = UIViewContentModeScaleToFill;
cell.selectedBackgroundView = selectedCell;
[tableView setBackgroundColor:[UIColor clearColor]];
return cell;
}
//get cell accessory
-(UITableViewCellAccessoryType)tableView:(UITableView *)tableView
accessoryTypeForRowWithIndexPath:(NSIndexPath *)indexPath {
if(indexPath.row < [tweets count]){
}
return UITableViewCellAccessoryDisclosureIndicator;
}
// custom hieght
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath {
return 80;
}
//select tweet bring to detail view ..... Also bring in the Users information who made the tweet!
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
//Get the selected tweets
NSString *selectedTweet = [(Tweet*)[tweets objectAtIndex:indexPath.row] tweet];
NSString *selectedUser = [(Tweet*)[tweets objectAtIndex:indexPath.row] author];
NSString *selectedUserInfo = [(Tweet*)[tweets objectAtIndex:indexPath.row] user];
NSString *retweetCount = [(Tweet*)[tweets objectAtIndex:indexPath.row] reTweetCount ];
// NSString *selectedUserFriendsCount = [(Tweet*)[tweets objectAtIndex:indexPath.row] userFriendsCount];------HUH? NO soup for ME!
NSString *selectedUserFollowersCount = [(Tweet*)[tweets objectAtIndex:indexPath.row] userFollowersCount];
//Initialize the detail view controller and display it.
TwitterDetailViewController*dvController = [[TwitterDetailViewController alloc]
initWithNibName:#"TwitterDetailViewController" bundle:[NSBundle mainBundle]];
dvController.selectedTweet = selectedTweet;
dvController.selectedUser = selectedUser;
dvController.selectedUserInfo = selectedUserInfo;
// dvController.selectedUserFriendsCount = selectedUserFriendsCount;------Doesnt reconize the call for some odd reason!
dvController.selectedUserFollowersCount = selectedUserFollowersCount;
dvController.retweetCount = retweetCount;
dvController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:dvController animated:YES];
//[self.navigationController pushViewController:webController animated:YES];-------would rather use navagation controller for several obvious reasons
[dvController release];
dvController = nil;
}
UITableView doesn't it like it when you gave it something inconsistant. If you change the model, you need to call [tableView reloadData] or if you want to animate the changes call [tableView beingUpdate][tableView endUpdate] with all the insert/remove cell operations in the middle.
On another note, I'm not sure why you doing here:
NSString *identifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
[cell autorelease];
}
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:#"cell"];
[cell autorelease];
First if (cell == nil), calling auto release on it won't do anything.
The reuse identifier thing is a flyweight pattern. If dequeueReusableCellWithIdentifier: returns nil, it means it doesn't have a cell object in the pool for you to use and you should alloc a new one for it. dequeueReusableCellWithIdentifier also already returns an autorelease object.
Instead try this:
NSString *identifier = #"mytweetcell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier] autorelease];
}

Getting/Setting UITextField value in a table cell

For my current project i need to have a table in which contains textfield in each cell, the number of cells and textfield must be dynamic, it's depends on the number of data in a MutuableArray. I have the textfield in cells working, but i can't get/set the textfield value. I wonder if you guys can help me out or at least correct me what I did wrong? Thank's alot in advance. See code snippets below:
// Adds textfield into cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSUInteger row = indexPath.row;
X10ArchiefIndexDefs *curIndex = [indexDefinities objectAtIndex:row];
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
BOOL bShowSelection = ([curIndex.HasVasteWaarden isEqualToString:#"false"]);
if (bShowSelection) {
bShowSelection = !([curIndex.DataType isEqualToString:#"Datum"]);
}
if ([indexPath section] == 0) {
if (bShowSelection) {
cell.accessoryType = UITableViewCellAccessoryNone;
} else {
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
}
UITextField *editField = [[UITextField alloc] initWithFrame:CGRectMake(110, 10, 185, 30)];
editField.adjustsFontSizeToFitWidth = YES;
editField.textColor = [UIColor blackColor];
editField.placeholder = curIndex.Naam;
editField.keyboardType = UIKeyboardTypeDefault;
editField.returnKeyType = UIReturnKeyNext;
editField.backgroundColor = [UIColor whiteColor];
editField.autocorrectionType = UITextAutocorrectionTypeNo; // no auto correction support
editField.autocapitalizationType = UITextAutocapitalizationTypeNone; // no auto capitalization support
editField.textAlignment = UITextAlignmentLeft;
editField.clearButtonMode = UITextFieldViewModeNever; // no clear 'x' button to the right
editField.tag = [curIndex.UID intValue];
[editField setEnabled: YES];
[cell addSubview:editField];
[editField release];
}
}
return cell;
}
In some case i'm using popovercontroller to display list of data. User can select a value uit of the popup. This code is executed when there is a value selected:
- (void)selectedValue:(NSString *) value {
//---update value of the text field ---
//The first attempt it doesn't put the text to text field
//static NSString *CellIdentifier = #"Cell";
//UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//
//if (cell == nil) {
// cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
//}
// second attempt it crashes
X10ArchiefIndexDefs *curIndex = [indexDefinities objectAtIndex:curRow.row];
int index = [curIndex.UID intValue];
UITextField *textField = (UITextField *) [curCell viewWithTag: index];
if (textField) {
[textField setText:value];
}
[textField release];
[self.popOverController dismissPopoverAnimated:YES];
}
When cell is selected I'm making sure that the cell is saved for use later.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
X10ArchiefIndexDefs *curIndex = [indexDefinities objectAtIndex:indexPath.row];
if (!curIndex) {
return;
}
curRow = indexPath; // saves the selected row
if ([curIndex.VasteWaarden count] > 0) {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
curCell = cell; // saves the selected cell
CGRect frame = [cell.superview convertRect:cell.frame toView:self.view];
self.detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
detailViewController.delegate = self;
self.popOverController = [[[UIPopoverController alloc] initWithContentViewController:detailViewController] autorelease];
X10ArchiefIndexDefs *curIndex = [indexDefinities objectAtIndex:indexPath.row];
self.detailViewController.Values = curIndex.VasteWaarden;
[self.popOverController presentPopoverFromRect:frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
}
Again thank's alot in advance.
Cheers,
Inoel
In the second code snippet you are releasing the textField. You shouldn't do this because you haven't retained it. Because viewWithTag: simple gets a reference to the text field it doesn't retain the textField. So you are releasing it more times that it has been retained, so the retainCount reaches 0 and the textfield is dealloced from memory. Then when you attempt it the second time there is no textfield in the memory.
Just remove the:
[textField release];
From the second code snippet. If you don't understand why, then read some articles about memory management (just google it). It takes some time to understand it fully, at least I know it took me a while :)

UITableView reloading data / refreshing (possible duplication issue)

I have a UITableView in an iPhone application which I am refreshing (by calling [self.tableView reloadData] in the action method for a UISegmentedControl dynamically embedded in one of the UITableView cells. The table view is refreshed to update a text value for one of the cells.
However, the following code seems to produce an unwanted side-effect. It appears that each time the UITableView refreshes it creates a new instance of the UISegmentedControl (and possibly the images - I'm not sure) over the existing one(s).
The only reason I notice this is that with each refresh a barely perceptible border starts to form around the UISegmentedControl and the application slows noticeably. I would be extremely grateful for any suggestions/code-solutions to my current predicament.
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
NSUInteger section = indexPath.section;
NSUInteger row = indexPath.row;
// Set up the cell...
//populates the personal info section
if (section == kPersonalInfoAddSection) {
if (row == kNameRow) {
//Other code irrelevant to this question was removed for the sake of clarity
}
else if(row == kHeightRow) {
cell.imageView.image = [UIImage imageNamed:#"tableview_height_label.png"];
//THIS IS THE TEXT I'M TRYING TO UPDATE
cell.textLabel.text = [Formatter formatHeightValue:mainUser.heightInMM forZone:self.heightZone];
cell.detailTextLabel.text = REQUIRED_STRING;
}
}
//populates the units section
if (section == kUnitsSection) {
if (row == kHeightUnitsRow) {
NSArray *heightUnitsSegments = [[NSArray alloc] initWithObjects:FT_AND_IN_STRING, M_AND_CM_STRING, nil];
UISegmentedControl *heightUnitControl = [[UISegmentedControl alloc] initWithItems:heightUnitsSegments];
CGRect segmentRect = CGRectMake(90, 7, 200, 30);
[heightUnitControl setFrame:segmentRect];
//[heightUnitControl setSelectedSegmentIndex:0];
[heightUnitControl addTarget:self action:#selector(heightSegmentClicked:) forControlEvents:UIControlEventValueChanged];
heightUnitControl.tag = kHeightSegmentedControlTag;
cell.textLabel.text = #"Height:";
cell.detailTextLabel.text = #"(units)";
[cell.contentView addSubview:heightUnitControl];
[heightUnitsSegments release];
[heightUnitControl release];
}
else if(row == kWeightUnitsRow) {
//Other code irrelevant to this question was removed for the sake of clarity
}
}
return cell;
}
Thank you all in advance!
You're right, it is creating a new instance of the UISegmentedControl. It's because you are using a generic cell identifier, #"Cell", then adding the UISegmentedControl each time, never removing it. The cells get cached containing the UISegmentedControl, you retrieve the cached cell and add the control again.
You could use a more specific cell identifier and if cell != nil you know it contains the UISegmentedControl already. Or create a new cell each time that way you're not using a cached cell that already contains the control.
With the image view you just set the cells image view property without adding a new view to the cell so that one is ok, it gets replaced each time.
Since the text you are trying to update doesn't have to do with the UISegmentedControl I think you should be able to use a more specific cell identifier and add the control only on cell creation.
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *arr1=[NSArray arrayWithObjects:#"img1.jpg",#"img2.jpg",nil];
NSArray *arr2=[NSArray arrayWithObjects:#"img1.jpg",#"img2.jpg",#"img3.jpg",#"img4.jpg",#"img5.jpg",#"img6.jpg",nil];
NSArray *arr3=[NSArray arrayWithObjects:#"img6.jpg",#"img5.jpg",#"img2.jpg",#"img1.jpg",nil];
Imgs = [[NSArray alloc] initWithArray:[NSArray arrayWithObjects:arr1,arr2,arr3,nil]];
NSDictionary *dic1=[NSDictionary dictionaryWithObjectsAndKeys:#"Ahmedabad",#"Name",#"Picture 5.png",#"Rating",#"Picture 1.png",#"Photo",arr1,#"img",nil];
NSDictionary *dic2=[NSDictionary dictionaryWithObjectsAndKeys:#"Rajkot",#"Name",#"Picture 5.png",#"Rating",#"Picture 2.png",#"Photo",nil];
NSDictionary *dic3=[NSDictionary dictionaryWithObjectsAndKeys:#"Baroda",#"Name",#"Picture 5.png",#"Rating",#"Picture 7.png",#"Photo",nil];
tblArray=[[NSArray alloc] initWithObjects:dic1,dic2,dic3,nil];
[myTbl reloadData];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.navigationController.navigationBarHidden=NO;
[self.navigationController.navigationBar setUserInteractionEnabled:YES];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
self.navigationController.navigationBarHidden=YES;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [tblArray count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *CellIdentifer=[NSString stringWithFormat:#"%i",indexPath.row];
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:CellIdentifer];
if(cell==nil){
cell=[self myCustomCell:CellIdentifer dicToSet:[tblArray objectAtIndex:indexPath.row]];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
}
return cell;
}
-(UITableViewCell*)myCustomCell:(NSString*)CellIdentifer dicToSet:(NSDictionary*)dicToSet{
UITableViewCell *cell=[[[UITableViewCell alloc] initWithFrame:CGRectMake(0, 0, 320, 44) reuseIdentifier:CellIdentifer] autorelease];
UIImageView *imgV=[[UIImageView alloc] initWithFrame:CGRectMake(2, 2, 40, 40)];
[imgV setImage:[UIImage imageNamed:[dicToSet valueForKey:#"Photo"]]];
[cell addSubview:imgV];
[imgV release];
UILabel *lbl=[[UILabel alloc] initWithFrame:CGRectMake(44, 2, 276, 20)];
[lbl setText:[dicToSet valueForKey:#"Name"]];
[cell addSubview:lbl];
[lbl setBackgroundColor:[UIColor clearColor]];
[lbl setFont:[UIFont fontWithName:#"Helvetica-Bold" size:18]];
[lbl release];
UIImageView *imgV1=[[UIImageView alloc] initWithFrame:CGRectMake(44, 24, 70, 20)];
[imgV1 setImage:[UIImage imageNamed:[dicToSet valueForKey:#"Rating"]]];
[cell addSubview:imgV1];
[imgV1 release];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
nxtPlcDtl=[[plcFullDtl alloc] initWithNibName:#"plcFullDtl" bundle:nil];
nxtPlcDtl.dict=[[NSDictionary alloc] initWithDictionary:[tblArray objectAtIndex:indexPath.row]];
nxtPlcDtl.Imgs = [Imgs objectAtIndex:indexPath.row];
nxtPlcDtl.comment1 = [comment1 objectAtIndex:indexPath.row];
nxtPlcDtl.vedio = [vedio objectAtIndex:indexPath.row];
[self.navigationController pushViewController:nxtPlcDtl animated:YES];
}