So far, have read a few posts, such as this and this, but they have not really helped with my situation.
I'm creating a dynamic form for iPad using 'plain' style UITableViews. I have multiple different UITableViews on the page, so I defined a separate object to server as my datasource and delegate. I understand how to change the text of each cell using the datasource; however, I have no clue how to link the UITextFields in my prototype cells to an IBAction. I could figure out how to create a single IBAction for all textfields in my table, such that they all update the same data, but I don't know how to have each UITextField have a one-to-one correspondence with my datasource.
Here is my prototype cell:
and my code thus far:
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"myPrototypeCell"];
UILabel *buildingNumber = (UILabel *)[cell viewWithTag:100];
buildingNumber.text = [#"Building " stringByAppendingString:self.dataSource[indexPath.row][#"buildingNumber"]];
return cell;
}
self.dataSource is an NSMutableArray of NSMutableDictionaries.
Any help whatsoever is appreciated.
I initially thought you were referring to IBOutlets so my previous answer is somehow wrong but the inherent idea is still the same.
You cannot have IBActions or IBOutlets from a prototype cell unless the cell is subclassed. You can do so if the cells are static though, not that it can help in your case. Subclassing the UITableViewCell is not too hard or too bad, in fact if in the future you want to speed things up on your TableView, that is one of the many ways to start.
This tutorial provides a few different options for dealing with information inside a table view cell:
http://mobile.tutsplus.com/tutorials/iphone/customizing-uitableview-cell/
I almost always use a UITableViewCell subclass to deal with outlets and actions inside the cell. But this should be a decision you make based on your own architecture.
Hope this helps!
you need single for all your textField.So do the following:
Get the text field as your are getting label
UITextField *yourTextField = (UITextField *)[cell viewWithTag:101];
[yourTextField addTarget:self action:#selector(clickTextField:) forControlEvents:UIControlEventEditingChanged];
clickTextField method will get invoke for every Text Field.
Hope this helps.
Edit: Forgot to mention, you can you set delegate of UItextField and get a notification in UITextFieldTextDidChange: delegate method
Related
I place textview in the prototype cells by storyboard and assign the textview's tag.
In the implantation method of
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:,
I wanna assign the textview another identifier so that I can obtain the textview by this identifier. The reason why I don't use the TAG property to do this is because that all the cells in my table view has the same prototype for reusing.
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
ETPost *post = postList[indexPath.row];
UITextView *textView = (UITextView*)[cell viewWithTag:TEXT_TAG];//TEXT_TAG 1000
textView.text =post.content;
return cell;
}
as you can see above, I use the viewWithTag, all the cells in my tableview have the same tag, so I have to another solution instead of assigning the indexPath to the TAG.
Alright, the answer is probably simpler than you think. But just subclass UITableViewCell and make sure that your table view is using your new subclass (you set this up in the prototype cell Custom Class in IB and StoryBoards). The only thing the subclass adds is a property that allows you to identify it.
#property short specialIdentifier;
Here's a more general link on UITableViewCells which I generally refer to when I need something done: cusomizing uitableviewcells
in -(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath: you could assign the indexPath's row number to your textView's tag like:
cell.textView.tag = indexPath.row;
so this tag would correspond with your cell's indexPath distinct assuming you place all cells in ONE section.
I have read many posts about similar problems but nothing seems to work, I am obviously doing something wrong. I have a TableViewController that is in a StoryBoard (XCode 5). For the PrototypeCell I set the type to custom and set the Identifier to "pbvcell". I added some labels, changed the background etc.. Here is my tableview delegate method for setting the cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"pbvcell"];
// Configure the cell...
PBVlead *lead = [self.leads objectAtIndex:indexPath.row];
NSLog(#"Cell class %#", [cell class]);
UILabel *leadNameLabel = (UILabel *)[cell viewWithTag:1];
leadNameLabel.text = lead.leadName;
return cell;
}
Now the app launches but even after I add an object to the tableview datasource array and do a reload data, the cells are blank, like the custom cell is not being used. It looks like this should be easy and thats all I need to do. What on earth am I missing?
I left this in a comment above but just to keep things tidy I will post it as an answer here. It is silly but it is good to note that you have to manipulate the contextView of a prototype cell and not the tableview cell itself in order for your visual changes to have an effect...
"Because I embrace my own stupidity I will tell everyone what was going on here. I had set the TableCell background to blue and added some UILabels and set there color to white to show up against the blue background. Run the app, no labels.... What I finally realized is, I had not set the Content View background to blue. So..... What was happening was the labels actually are shown in the content view in the view hierarchy. White labels on a white background equals, invisible... :-) I set the content view background to blue and wola, there is everything! :-) Brother..?
I have a UITableView that I want to alter some of the static cells after I do other processing. I have outlets set up for the cells that I want to modify, but when I look at them using NSLog, they show nil, which indicates to me that I don't have the correct cell. For instance, in the image below I want to add the start time to the label just like I did for Date (date was done when creating the cells for which I got the current date),
I tap on the disclosure indicator which takes me to another scene (this was created in Storyboard, using segues to get from one scene to another) where I get the two times I need. I then return to the main scene (shown) and try to alter the Start Time label, but nothing happens. A NSLog of the label prior to trying to alter it returns this:
oStartTimeCell.textLabel.text: (null)
I have read in one of the Apple docs that this textfield is read-only. If that is true in this case, is there a way I can reload the cells with the updated information? Or is there another way to do this?
You're using the wrong approach. You should not create a reference to a cell using an outlet. Once the cell moves out of the visible view, the outlet will either be null or contain garbage data. Even if (in your situation) the cell will never move out of view, I think it shows you're trying to use a UITableView in a way that was not meant to be.
Instead put the data you want to display in your cells in a dataSource, e.g. an array.
The tableView should use the dataSource to configure the values displayed in the textLabels of the cells. Once you want to update the text displayed in the cells, change the values in the dataSource and call reloadData on the tableView to force the tableView to call -tableView:cellForRowAtIndexPath: and related UITableViewDataSource methods.
Try to create an IBOutlet for each cell and connect it:
IBOutlet UITableViewCell *cell1;
IBOutlet UITableViewCell *cell2;
IBOutlet UITableViewCell *cell3;
And also change your method to:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(indexPath.row == 0) return cell1;
if(indexPath.row == 1) return cell2;
if(indexPath.row == 2) return cell3;
if (cell == nil) {
//create cell;
}
return cell;
}
Are you using a UILabel to display the text ? . If you are just create an outlet to the UIlabel and update it any method like cellForRwoAtIndexPath or didSelectRowAtIndexPath etc that is called after you tableView is loaded.
If you are not using a UILabel and just using cell.textLabel you could do something like
cell.textLabel.text = #"ChangedText" in cellForRowAtIndexPathMethod. Make sure you are editing the required cell by checking indexPath.row
Do [tableView reloadData] to call cellForRowAtIndexPath.
I have a UITableViewController with prototype cells containing UITextFields. To configure these custome cells, I've created a UITableViewCell subclass. I've conected the textField to the cell subclass via an outlet (nonatomic, weak).
On this subclass I've created a protocol for which the UITableViewController is its delegate so that everytime something changes in these textFields, the TableViewController knows about it. Basically I wanted this to save the values on the NSUserDefaults
Besides, in order to dynamically obtain values from these textFields, I can do something like this:
((TextFieldCell*)[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]]).textField.text
It works ok most of the times. However when the textField is outside of the view because it has scrolled, the vaulue I get from textField.text is (null). As soon as it gets in the view again, everything goes back to normal.
I tried to change the outlet from weak to strong but to no avail.
I guess I could define some private NSStrings on the class, and fill them out when the delegate protocol gets called. The thing is that I wanted to get my code as generic as possible, keeping the need for private variables as low as possible, mostly to simplify the cell generation code.
Is there any other way to get the values of the textFields when they are outside of the view?
Thanks in advance!
But you know that UITableView only keeps Cells for the visible rect?
When a cell leaves the screen, and a new cell is needed for another cell moving into the visible area, the old cell is reused for the new content.
So there is not one cell for each row of your table view.
And if your table contains a lot data, there are far more rows than cells.
As Thyraz said, the UITableView only keeps cells for the visible rect -- and a reasonable buffer to allow for scrolling. Thats why 'reuse identifiers' are so very important, they indicate which cells can be used for which tables (critical when you have more than one table to worry about). Unfortunately, that doesn't answer your question by itself.
The responsibility for storing the contents of those textViews isn't on the UITableView's shoulders. It's your job to provide that data through the data source delegate protocols, and therefore you should be querying the data source for that information.
Edit: Which means that yes, you should be storing this data somewhere else, usually in the form of properties on the view controller class that contains the table view. I'd recommend the use of NSArray for the purpose, but you can also do it through dicts or even, at the last resort (and this is more a in theory you can do this, but it's an incredibly bad idea kind of thing), a series of properties. Personally, I almost always use NSArrays because they're structured in a manner appropriate to the problem, but you could theoretically do it other ways. (I've used a dict based structure exactly once, and that was a situation where my data was nested inside itself in a recursive structure)
UITableViewController doesn't keep cells around once off the screen. You can use the following pattern to get a previously used one as a memory management optimization, but you MUST assume that cells need to have the values reset on them every time they come onto the screen (even if dequeued) because there is no guarantee what the values will be.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier1 = #"Cell1";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier2];
if( cell == nil ) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier1] autorelease];
cell2.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell2.editingAccessoryType = UITableViewCellAccessoryNone;
}
switch( indexPath.section ) {
case first_Section:
if( row == 0 ) {
cell1.textLabel.text = #"Some Text";
cell1.accessoryView = [self myCustomViewControl];
cell = cell1;
}
... etc
}
}
Is there a way to get or set the textLabel of a standard UITableViewCell inside a custom method? For instance of a pseudo code,
-(void)getTextLabelOfUITableViewCell
{
UILabel *tempLabel = [[UITableViewCell section:0 row:1] textLabel];
}
-(void)setTextLabelOfUITableViewCell:(UILabel *)data
{
[[UITableViewCell section:0 row:1] textLabel] = data;
}
I'm trying to bind this with the PickerView delegate methods so whenever I change values in the datepicker or picker, the selected UITableViewCell will reflect the changes.
Otherwise I'd have to create a custom UITableViewCell. It'd be nice to be able to programmatically use the standard UITableViewCell Styles.
Thanks in advance!
You should keep (or pass) a reference to the "currently selected cell". Then you can easily access its text label by simply writing:
// assuming the selected cell is kept in a property by name selectedTableViewCell
UILabel * tempLabel = self.selectedTableViewCell.textLabel;
In case you're wondering how to keep such a reference, you should implement the
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
method, and in it, simply state:
self.selectedTableViewCell = [tableView cellForRowAtIndexPath:indexPath];
This way, when the user taps the cell, it will be set as the "selected cell".
Another way to fly would be by adding the reference to the cell you want to edit the text from in the IBAction as a parameter, like this:
-(IBAction)getTextLabelOfUITableViewCell:(UITableViewCell *)editMe;
And then you could write something like:
UILabel * tempLabel = editMe.textLabel;
You pretty much can do whatever you want with the label from there on.
Hope this helps!