There are hundreds of articles explaining how to set data to a tableview but I couldn't find any for getting data from it.
For example, if a have a tableview with 3 rows and in each row I have 3 textfields, what is the best way to get these textfields?
Xcode 61 doesn't let me to create static cells and if I create 3 prototype cells, it doesn't allow me to create 9 different textfields (so I could manage the info separately).
So I understand I have to create 3 textfields in a prototype cell and then differentiate each row, but how can I differentiate each row in the function "cellForRowAtIndexpath"?
I'd appreciate every other solution.
Thanks in advance.
You can set tag value to each textField from your "cellForRowAtIndexpath".
cell.TextField.tag = indexPath.row;
Take one mutable array.
Now when you textfield delegate method call, you can update or capture textFields value in array according to tag, and use for further process. Some thing like below.
-(void)textViewDidEndEditing:(UITextView *)textView
{
if([array count] > textView.tag)
{
[array replaceObjectAtIndex:textView.tag withObject:textView.text];
}
}
- (void)textViewDidChange:(UITextView *)textView
{
if([array count] > textView.tag)
{
[array replaceObjectAtIndex:textView.tag withObject:textView.text];
}
}
If you are not clear let me know.
best way I know of; if you're adding subview like a textField would probably be to tag them with restorationIdentifiers.
I think there is also a method for tableView that has something to do with accessoryViewDidChange or something
or add a target for the field and use didPerFormAction: maybe..
how did you configure the cell when you added the text field?
Related
I have a UITableView and each UITableViewCell contains an editable UITextView.
My data source is a NSMutableArray containing NSMutableDictionary that holds the text value and some styling keys for the text.
How can I (efficiently) make it so that any changes a user makes to the UITextView are updated in the corresponding datasource NSMutableDictionary?
A rather simple way is to utilize the index path of the table, it is NOT the cleanest so it depends on the complexity of your datasource, and if you have multiple tables etc.
What you can do is when the user ends editing the textView or selects another row in tableView, you read the indexPath of the selected row (That requires that the row keeps actually being in the selected state while editing the textView which it should by default). From there you call your update method.
To catch the end of editing you implement
-(void)textViewDidEndEditing:(UITextView *)textView
{
NSIndexPath *selectedpath = [myTable indexPathForSelectedRow];
[self myUpdateMethodForIndexPath:selectedpath];
}
To catch deselect of the table row and the above doesnt get called, you implement
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self myUpdateMethodForIndexPath:indexPath];
}
Your update method must then read the value of the textView at the corresponding cell at the indexPath and handle this in the datasource. To care for sections of course you need to correctly handle the indexPath, in the example just the row is used (1 section).
-(void)myUpdateMethodForIndexPath:(NSIndexPath *)editPath
{
UITableViewCell *editCell = [myTable cellForRowAtIndexPath:editPath];
NSString *newText = editCell.theTextView.text;
....
NSMutableDictionary *dict = [myDictArray objectAtIndex:editPath.row];
....
}
First of all, you must assign a tag to each UITextView, to know exactly which UITextView are you refering.
Then you must implement UITextViewDelegate in your view controller which holds the tableview. Then, make this view controller the delegate of each UITextView. Read here how to implement it: UITextViewDelegate reference.
Look for the protocol method that better fits your needs (probably – textView:shouldChangeTextInRange:replacementText:, wich is called each time the text changes in any range.
In the delegate method, you can read the text with UITextView.text property, and assign this value to your data model (the dictionary).
Another possible approach is to use KVO pattern, but it requires more coding and a better understanding both, the pattern and the implementation. Hope it helps!
Make your view controller the delegate of each text view. Listen for appropriate events to get the updated text. Then have the view controller update the data model with the updated text.
If you have custom cells then have the cell be the text view delegate. Then the cell should notify its delegate (the view controller) about the updated text. Of course this requires that your custom cell class define its own delegate protocol and the view controller should make itself the delegate of each cell.
That's as specific as an answer can be for such a vague question.
I have a UITableView with over 50 rows but only 5 are shown at a time. How can I force the middle row to always be selected? For example 2,3,4,5,6 are shown, 4 will be selected.
The user scrolls -> 14,15,16,17,18 , 16 will be selected etc'.
Thanks
This method worked pretty well for me. I had a table view that showed 5 rows at a time, but when I log visibleRows, I always got a count of 7, so I get the index paths for those seven, and select the middle one (index 3):
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
NSArray *vis = self.tableView.indexPathsForVisibleRows;
if (vis.count %2 == 1) {
[self.tableView selectRowAtIndexPath:vis[3] animated:NO scrollPosition:UITableViewScrollPositionNone];
}
}
Use the tableView:willDisplayCell:forRowAtIndexPath: method that is part of the UITableViewDelegate protocol.
In here you can check the indexPath.row value, and if it is within your specified range, use cell.selected.
Further information:
http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewDelegate_Protocol/Reference/Reference.html
Although I recommend you maintain whether or not a cell should be selected within your datasource, rather than hooking into the position of a cell, this way you can check your datasource if a cell should be selected rather than forcing yourself to use a particular index cell for a particular thing.
Hope this helps.
Purpose is UIPickerView custom i think,
Take a look here and this question will help you
I'm trying to create a view similar to add/edit contact in iOS and there are a few things that are happening, and I'm not sure how they are implemented. Any help in understanding is greatly appreciated.
For each section in contacts i.e. name, phone number, email, etc are these each their own tableview or are these sections within a larger tableview?
When clicking done when adding or editing a contact, the unused tableview cells disappear. Is this using deleteRowsAtIndexPaths:withRowAnimation: or is there a hide method I haven't found? If it is using that method, then when clicking the edit contact button, how does the view brings back these unused tableview cells?
When clicking on a cell in the tableview cell when editing a contact, you are able to change the text. Is this a textfield within a tableview cell or is it actually modifying the label of the tableview cell?
I am not looking for any specific code, as a fairly new programmer I am just trying to understand the strategies/best way to implement these features.
I tried a lot different ways to implement that. the easiest one: Subclass UITableViewCell and overwrite setFrame:. note that this is easy to achieve for grouped tables, but hard for plain ones. in the datasource's tableView:cellForRowAtIndexPath: create an object of this custom cell for the first section. use another identifier for cells of that section, so that only the correct cells will be re-used.
yes, I assume that. The controller has some sort of definition how many cells has to be show in edit mode and how many are actually used with some sort of information. you can easily create a array of indexPaths that must be deleted.
I would do it in tableView:didSelectRowAtIndexPath: by fetching the cell via tableView:cellForRowAtIndexPath:, hide the label and unhide or add a textfield and make this first responder.
code for 1.
the cell
#interface InsetCell : UITableViewCell
#property(nonatomic)CGFloat inset;
#end
#implementation InsetCell
- (void)setFrame:(CGRect)frame {
CGFloat inset;
if (_inset == 0) {
inset = 70; //default value
} else {
inset = _inset;
}
frame.origin.x += inset;
[super setFrame:frame];
}
-(void)setInset:(CGFloat)inset
{
_inset = inset;
[self setNeedsLayout];
}
#end
a project that uses similar code
I have a UITableView with custom cells,, I want to set background images of those custom cells. The background image of first and the last cell of the UITableView should be different than other cells.
I have used dequeueReusableCellWithIdentifier: to create the cell.
to set the background images of the first cell, I wrote
`
if (indexPath.row==0) {
cell.cellBackgrounfImage.image=[UIImage imageNamed:#"TopCellImage.png"];
}
`
1) Because of the reusing cell,,, this is going to set middle cell image rarther than the first cell. How can I overcome this problem
2) How to access the last cell of the UITableView to set other image
Please anyone give me a solutions for these 2 questions.
Thanks
For Step 1)
When you are scrolling tableview, it will be always reload data. So may be it will generate background image for middle one.
But, if you are set indexpath.row == 0 condition, then it will not affect any row instead of first one.
For Step 2)
You can get values for no of arrays (Array Count).
suppose int totalArr = [arr count];
Then apply condition same as first row by,
if(indexpath.row == (totalArr - 1) {
cell.cellBackgrounfImage.image=[UIImage imageNamed:#"BottomCellImage.png"]; }
So, it will work for last one also.
Thanks.
I have a tableview with multiple dynamic tableview cells, and inside each tableviewcell i have multiple textfields. Each cell has a different tag, but the texfields don´t! and i need to retrieve the information the user will insert later on them. I´m using the interface builder.
Is it possible to access a texfield that isn´t tagged?.
Can i manage this using the "user defined Runtime Attributes"?.
Thanks
This is a common mistake when starting with iOS.
You should not be referring directly to the textfield in order to retrieve the information stored in it, especially in a table view. In a table view, when a cell scrolls off the screen, the cell will very likely get reused and the information that was stored there is gone forever.
Instead, store the text when the user finishes editing the textfield by setting your view controller as the textfield delegate and then implementing the textFieldDidEndEditing: delegate method:
- (void)textFieldDidEndEditing:(UITextField *)textField
{
// Store the textField.text value somewhere for later use.
}
You can go over each cell subviews and check if it a UITextField, something like:
for (UIView *subview in cell.subviews) {
if ([subview isKindOfClass:[UITextField class]]) {
// do something with the text field...
}
}
Having said that, this is probably not the best approach... U will do better given each textField a tag or subclassing the cell with a custom cell that has textFields as properties.