Hey everybody, I had a question about editing the value of a table cell and returning the edited value back to the original cell.
I have a UITableView which contains 5 sections of 1 row each. Within cellForRowAtIndexPath I have the following:
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
}
NSString *fieldTitle;
switch (indexPath.section)
{
case 0:
fieldTitle = #"First Name";
break;
case 1:
fieldTitle = #"Last Name";
break;
case 2:
fieldTitle = #"Company";
break;
case 3:
fieldTitle = #"Email Address";
break;
case 4:
fieldTitle = #"Password";
break;
}
cell.textLabel.text = fieldTitle;
When a row is clicked, didSelectRowAtIndexPath is fired as follows:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
AddField *addField = [[AddField alloc] initWithStyle:UITableViewStyleGrouped];
addField.field = cell.textLabel.text;
addField.title = cell.textLabel.text;
addField.value = cell.detailTextLabel.text;
[self.navigationController pushViewController:addField animated:YES];
}
This sets up another UITableView that contains one section and one row. This table utilizes a custom cell I wrote that contains a text field the user can edit. There is a done button the user can click to go back to the previous view.
My question is this: How do I get the value the user entered in the AddField view to appear in the detailText label on the selected table cell in the previous view? This functionality would be very similar to adding the title of a new event in the iPhone's native calendar application.
Thanks for any help I can get, and let me know if you need more information.
Have you tried calling reloadData on the original tableView? Of course you would need chnage your code so that fieldTitle to get its values from an array of NSStrings......and set the tableview datasource to that array....
You would use delegates for this. Declare a protocol which is your cell delegate as follows (from memory so apologies if it doesn't compile):
#protocol CellDelegate
#required
- (void) fieldValueChanged:(AddField *)field;
#end
Add an "id delegate" to your custom cell class, and add a property (nonatomic, assign) and synthesise it.
Then when you setup your cell in didSelectRowAtIndexPath you do the following:
[cell setDelegate:self];
Now in you view controller you simply implement that protocol (CellDelegate), implement the method fieldValueChanged.... this will get called by the cell.
Now in the cell when the value is changed simply call [delegate fieldValueChanged:addfield];
NOTE: really you should be setting up the AddField WITHIN the custom cell class you write...
Related
I have 10 UITableViewCells in my UITableView. Each cell has a UITextField. They load fine, but I need a way to set each cell's text to its associated string.
Is there a delegate of UITextField that I can use to do this, and how can I determine which textfield belongs to what NSString, etc?
Edit:
Here is a picture of my tableView. I want it to load text into each cell's textfield from the server then the user can edit it. Or if there is no data on the server, the textfield will be blank and the user can add data and it will sync back.
I have created an NSString for each cell, such as temperatureString, pulseString, etc.
Edit: In respect to the new info this is my new solution
So by the looks of it you are inserting UITextField into each cell, instead of setting the tag of each cell set the tag for each UITextField
First Define your tags
#define DESCRIPTIVE_TAG_VALUE_1 10
#define DESCRIPTIVE_TAG_VALUE_2 11
#define DESCRIPTIVE_TAG_VALUE_3 12
...
Use these in your UITextField Delegate to determine which UITextField belongs to which NSString that is if you are syncing with each update, if your not. Then obtain a reference to the UITableView and retrieve each of the text values of each subview of a cell that has a tag equal to one of your defines (again in a switch statement).
Once again in when working with iOS use tags they are your friends
OR
Also you said that you are holding a reference to each NSString, you could just hold a reference to each UITextField instead that way when you sync you just have to retieve from each of your UITextField references.
But the Apple's best practises say to exercise the use of unique tags when dealing with mutliple views. It's really up to you
UITextfield is a subclass of UIView which has a 'tag' property. You can assign the cell's indexPath.row to be it's text field's tag as identification.
Based on your comment in response to #Javy (which contains extra information you should consider adding to your original question), you could do something like the following:
UITableViewCell *cell = nil;
NSString *key = nil;
switch (indexPath.row)
{
case 0:
cell = self.temperatureCell;
key = #"temperature";
break;
case 1:
// Do other cases similarly ...
}
NSString *text = [self.childAppointmentDictionary objectForKey:key];
cell.textField.text = text;
You should be setting the text in tableView: cellForRowAtIndexPath:
It sounds like you have a specific order that you want your items to appear in which would be a good time to use an NSArray, rather than an NSDictionary.
You could, in init, or initwithNibName, create a retained array property:
self.myListArray = [NSArray arrayWithObjects:#"fever", #"cough", #"runny nose", nil];
Then, assuming that you only have 1 section, you would do cell.textField.text = [self.myListArray objectAtIndex:indexPath.row];
Is there a reason that you're using an NSDictionary for this rather than an NSArray?
You must store a reference to each text field when they are created, so in the:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Method, you would add this line:
[myTextFieldArray addObject: cell.textField];
Assuming textField is the property for your custom tabel view cell.
You would also set the text within the text field just after the if (cell == nil) method.
The delegate methods simply allow you to know when text is being typed, etc.
EDIT:
Considering what you've added, I agree with Sid and CStreel. Create the tags for each value:
#define kTemperatureTag 0
#define kPulseTag 1
// etc.
As an alternative to CStreel, I would assign/retrieve info matching the indexPath row, and not worry about assigning tags, because they will be the same thing if you start your tags at zero.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// setup / retrieve cell
NSInteger index = [indexPath row];
switch(index)
{
case kTemperatureTag:
cell.textField.text = [self.childAppointmentDictionary objectForKey:#"temperature"];
break;
// case ...
}
// ..
}
And:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSInteger index = [indexPath row];
switch(index){
case kTemperatureTag:
[self.childAppointmentDictionary addObject:cell.textField.text forKey:#"temperature"];
I have UITableView.In that i have created custom cell with accessory button.Now by clicking on accessory button i want to create another view with edit cell functionality.For that how do i find the index path of that cell?and how do i pass the vales of that cell?
How do i call following method:
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
First thing to note here is that when you use custom accessoryView in a cell then the tableView:accessoryButtonTappedForRowWithIndexPath: delegate method would not be called. You have to add some target/action to the button you are adding as the custom accessory and handle the tap action yourself. You should add the custom accessory something like this,
UIButton *accessory = ...;
[accessory addTarget:self action:#selector(onCustomAccessoryTapped:) forControlEvents:UIControlEventTouchUpInside];
...
cell.accessoryView = accessory;
And in the onCustomAccessoryTapped: method you have to get the index path like this,
- (void)onCustomAccessoryTapped:(UIButton *)sender {
UITableViewCell *cell = (UITableViewCell *)sender.superview;
NSIndexPath *indexPath = [tableView indexPathForCell:cell];
// Now you can do the following
[self tableView:tableView accessoryButtonTappedForRowWithIndexPath:indexPath];
// Or you can do something else here to handle the action
}
The indexPath is passed as the second parameter to the method.
using "indexPathForCell" works as mentioned by emptystack
[yourViewController.tableView indexPathForCell: cell];
In addition if you are using tableview and a Search View, in your controller make sure to use searchDisplayController
NSIndexPath *indexPath;
NSDictionary *campaignMember;
if(self.searchDisplayController.isActive) {
indexPath = [[self.searchDisplayController searchResultsTableView] indexPathForCell: cell];
campaignMember = [self.filterResults objectAtIndex:indexPath.row];
} else {
indexPath = [self.tableView indexPathForCell: cell];
campaignMember = [self.dataRows objectAtIndex:indexPath.row];
}
NSString *id = [campaignMember objectForKey:#"Id"];
In my case "campaignMember" is a person object and I needed to get its id. "self.dataRows" is an array that holds main table data where as "self.filterResults" contains a subset or search/filter results of all the data based on search/filter criteria.
I am trying to pass the text lable that is in the uitableviewcell I have created but I am not sure of the parameters that are needed in order to do this.
I have an NSObject with a method that has an NSString object as a parameter, this is where I would like to pass the information from my uitableviewcell label too...
I have #imported the .h file and set up the object inside the views tableViews:didSelectRowAtIndexPath method but I am just not sure how to pass it the text from the lable, this is what I have tried but I have a compatibility warning..
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//initalize object to hold search parameters
VehicleSearchObject *vehicleSearchObject = [[VehicleSearchObject alloc] init];
[self.navigationController popViewControllerAnimated:YES]; //pops current view from the navigatoin stack
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
//--- this if block allows only one cell selection at a time and is passing the text in the cells label back to the object
if (oldCheckedData == nil) { // No selection made yet
oldCheckedData = indexPath;
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
[vehicleSearchObject GetManufacturers:[[cell textLabel] objectAtIndex:[indexPath row]] // This is where I try to pass the text back but not sure how to do it..
}
else {
UITableViewCell *formerSelectedcell = [tableView cellForRowAtIndexPath:oldCheckedData]; // finding the already selected cell
[formerSelectedcell setAccessoryType:UITableViewCellAccessoryNone];
[cell setAccessoryType:UITableViewCellAccessoryCheckmark]; // 'select' the new cell
oldCheckedData=indexPath;
}
}
You have to do this.
[vehicleSearchObject GetManufacturers:cell.textLabel.text];
You can reference the cell label text by simply doing:
cell.textLabel.text
i.e.
[vehicleSearchObject GetManufacturers:cell.textLabel.text];
[[cell textLabel] setText:[vehicleSearchObject GetManufacturers:[[cell textLabel] text]];
I have a basic view with a UITextField and a Tableview. I am able to enter text to the TextView and capture the value through an IBOutlet and IBAction.
My IBAction is setMyNote within which I call the cellForRow... method.
In my cellForRow.. method I have this snippet code
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSString *enNote = [[NSString alloc] initWithString:enteredNote.text];
NSInteger nRow = [indexPath row];
switch (nRow) {
case 1:
cell.textLabel.text = enNote;
break;
default:
break;
}
[enNote release];
return cell;
}
When I run my debugger, I can see that enNote has the new text I entered on the textView and it seems to get assigned to my cell.textLabel.text too -- but my table does not show this new text. What am I missing?
You shouldn't call the cellForRow directly.
When the table view renders itself it calls the cellForRow method in order to create the cells that should be visible.
I think that you should update your table view data source instead of trying to update the cell directly and then reload the table view ([tableView reloadData];).
I have a uitableview that is populated from a sqlite query.
I want to select or click on a row and then display that row's value in a uilabel field. To show the user that the row was selected.
I also want to pass that value on to different controllers that will be called later.
Here is a copy of my cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"psystem";
PSystem *psystem = [self.ppdm_systems objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Set up the cell...
// self.accessoryType = UITableViewCellAccessoryCheckmark;
cell.textLabel.text = psystem.system_id;
return cell;
}
I took out the _label.text .... in my various experiments.
Now what is not working is the passing of the value to different controllers.
Using the example listed here, the source controller is TableViewController and is where the value is set. The target controller is DetailViewController.
I can pass the title of the tab bar in, but that's from TableView --> DetailView.
I am not sure how to pull from tableview; ie: Tableview <-- DetailView when I am in DetailView.
thx
In your UIViewController, implement:
- (MyObject *)valueForSelectedRow {
MyCell *cell = (MyCell *)[self.tableView cellForRowAtIndexPath:[self.tableView indexPathForSelectedRow]];
return cell.myObject;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Get value
MyObject *object = [self valueForSelectedRow];
// Update the label, assumed that _label is a pointer to a UILabel view object.
_label.text = object.myValue;
}
When you want to push a new view controller, you just call -valueForSelectedRow and then use that value to push the controller.
This is assumed that you have a UITableViewCell subclass, with a property set to some model object. When you don't have that and just set the text property, that NSString object will be your 'model' object, although it would be easier when your cells handle custom model objects.
EDIT: Thanks for editing your answer. I now have the information I need. In this line: cell.textLabel.text = psystem.system_id, you setup the cell by simply setting the textLabel's text property. This is what I described in the paragraph above. I always create a UITableViewCell subclass, with a property set the the complete PSystem object. When you assign a PSystem object to the cell, it will handle it's contents, so you can easily manage your view in the, well, view. That's a very compelled approach since you never have to look at the controller again to alter the view's contents.
However, it can be done the way you currently have it. It would look something like:
- (NSString *)valueForSelectedRow {
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:[self.tableView indexPathForSelectedRow]];
return cell.textLabel.text;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Get value
NSString *value = [self valueForSelectedRow];
// Update the label, assumed that _label is a pointer to a UILabel view object.
_label.text = value;
}
In this case, your PSystem model has been replaced with an NSString object. For this, it's enough, but it could be so much easier to have the object itself. Okay, that can also be done by selecting the PSystem object again from the p_system array by the NSIndexPath, but things will become harder once you come up with more complex tableviews.