iphone: changing status of several segment controllers at once in custom cell - iphone

I have a tableView with the custom cell (see image below.)
Taking a three row table as an example, if a user changes segment controller in row 0 to "Yes," can I automatically change the segment controllers in rows 1 & 2 to "No?"
I am using the following to detect a segment change:
- (void)seg_changed:(id) sender {
cell=(switchCell*) [[sender superview] superview];
UITableView *table=(UITableView*) [cell superview];
NSIndexPath *path=[table indexPathForCell:cell];
NSLog(#"been pressed %d si %d",path.section, path.row);
}
Much appreciated.

In this method you call just tell those other segment controllers to set their values to "NO". The hard part is figuring out where those two other controls are. You have to do the hard work of tracking them.
If your design ensures there are always two more cell with segmented controls you can just access the correct cells by incrementing the path.row value.
This change can tell your data model that a value has changed, the model object then updates the associated values, and notifies the cells displaying those other values.
You can add an array to this cell class that keeps track of what other cells should be modified with this change.
Edit: (to respond to a comment) To change the setting displayed on the segmented control just set the property selectedSegmentIndex of the UISegmentedControl to the appropriate value. "Yes" should be 0, and "No" should be 1.

Related

Getting access to a UITableViewCell row that is currently not showing

Is there a way to get access to a UITableViewCell that is not currently on screen? I'm trying to update rows that are currently not in view. I am using this collapsable/expandable rows for a UITableView in one of Apple's example codes. I use this:
for (NSInteger row = 0; row < totalRows; row++) {
NSIndexPath *path = [NSIndexPath indexPathForRow:row inSection:section];
OrderTableViewCell *cell = (OrderTableViewCell *)[_tableView cellForRowAtIndexPath:path];
cell.CheckmarkButton.selected = YES;
cell.Symbol.isSelected = YES;
}
My totalRows is correct in that I get the number of rows from the TableView. So I thought I could use that, loop through all the rows, and set some values. However, if I check the state of the rows, the ones that are currently on screen have values and I can change them, but the ones off screen are null and cannot be set. Is there a way I can get around this? Thanks.
Depending on what you want to update you could just update the ith entry in a backing collection.
For example you could have a collection that stores bools corresponding to CheckmarkButton selected. In your loop you could set myArray[row] = YES. In cellForRowAtIndexPath you can do cell.CheckmarkButton.selected = myArray[indexPath.row].
If you want to maintain multiple items for each cell then myArray in the above example could contain instances of an object that holds values relevant to the ith cell.
Well why do you have to update a cell like that... If the cell is out of view, to save memory the system unloads it, and since its not in the view there is no need for you to update the cell directly, rather you should have the state be reflected in such way that when cellForRowIndexPath is called by the table view to load the cell the desired look is shown... The only reason youd want to do what you are doing is if the cell is showing and you need to update the cell, for the user... Even then you can still set your state and call the reloadRowsAtIndexPaths instead of manipulating the cell directly... Hope that helps

Preserve Cell Image After Scrolling UITableView

I have a custom UITableViewCell which acts as a check list. As the user clicks on the selected item, it goes from red to green indicating a selection, however as the users scrolls further down the list, once they come back up to the top, the image has changed back to it's default red value.
How do I go about preserving the state of an image as the tableview recycles cells?
Thanks
Sounds like you are using the UITableViewCells to store the state of your table data. This is the wrong approach because the cells are reused. You should keep state in an separate 'data store'. This can simply be an array you keep in memory in your UITableViewController subclass or something persistent like SQLite or Core Data. This state is then transferred back to the cell when the table view asks you to in tableView:cellForRowAtIndexPath:.
I had the same problem. Use:
MyTableViewCell* cell = [tableView dequeCellWithReuseIdentifier:#"MyTableViewCell"];
if (cell == nil) { /* create cell */ }
/* and now you reset the properties of that cell */
cell.text = [myCellText objectAtIndex:indexPath.row];
The key here is to reset the properties of dequeued table cell based on the indexPath. This does mean you will have to keep around enough state to re-create any table cell--including the images you are using.

iPhone: Cells order changes in UITableView Section After Call to reloadSections: Method

I have a table with two sections. A segmented control in first sections changes which rows are displayed in the second section. My problem is that the order of the rows and which row are displayed in the second section shifts improperly upon each subsequent press of a button in the segmented control.
I allow a user to add a product to a shopping list 3 different ways: by name, by barcord and by taking a picture with a camera. I have 3 buttons in a UISegmentedControl so the users can select which method to use. Depending on which segement the user selects the fields in the second segment should change to show cells relevant to that method.
Section 0:
0 row with segmented control showing name, barcode and camera buttons
Section 1:
// button zero, name button
0 row with textfield
1 row with textfield
or
// button 1, barcode button
0 row with textfield
or
// button 2, camera button
// shows camera view
I've put placeholders in each UITextField.
Each time a button in the segmented control is clicked, I call a pickOne: method that updates the tablevew. In that method, I construct a NSIndexSet with NSRange of (1, 1), and then I call the reloadSections: method of the UITableViewController with the NSIndexSet as a parameter.
When the view appears for the first time, everything is ok but when I click the buttons repeatedly, the order of the cells changes. Cells containing the two textFields for the button0 and the new placeHolders are written over the old ones.
Worse, sometimes when I click on button 0, it shows me only the second cell of the two cells.
My detailed code can be seen here http://pastebin.com/9GwMpCS9
I'm seeing a couple of problems.
The first big one is that you're adding subviews into the cells bypassing the contentView. Subviews in predefined styles are broken up into different parts depending on their roles. You have the editing control, the content view, and the accessory view. While you can add directly to the cell's view, there'll be odd behavior because the predefined cells are expecting the content to be in the content view.
I think what's causing your problem is that you're adding subviews every time a cell is decorated but you never remove them. When a cell is dequeued there's no guarantee that everything is restored to the pristine new condition as if it was alloc'ed. Things like custom accessory views that aren't removed can be left behind. I'm pretty sure that's happening. You're collecting visual trash on cells that should be clean.
I believe your problem is here.
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//....
if(addMode == NAME) {
if(indexPath.row == 0) {
[cell addSubview:nameTextField];
}
else if(indexPath.row == 1) {
[cell addSubview:categoryTextField];
}
}
else if(addMode == BARCODE) {
[cell addSubview:barcodeTextField];
}
else if(addMode == SCAN){
//Scanning mode
}
}
return cell;
}
This because the table always shows has having two sections, this method is always called for section 1. Regardless of the input type selected, it creates or dequeue a cell and returns it. Whenever addMode==SCAN, it randomly dequeues one of the previously used cells for the name or barcode addMode and returns that.
I suggest that you remove the SCAN logic from the table altogether or that you create a row for the camera.
I think the latter the best UI. With the first two buttons, the users is presented with a choice in the second section. You should maintain that pattern with the camera choice. Just have a cell that displays a button that evokes the camera. Yes, it adds a second step but establishes a kinetic pattern for the user: Select input type in section one then select an appropriate cell in section two. The user shouldn't have to stop and think each time whether they need to hit one of the rows in section two or not. They should just do so automatically.

How does one design the datasource for a UITableView in order to sort with a UISegmentedControl?

I am in the process of designing and coding an iPhone application to display movie times. I currently have a Movie Class which contains:
NSString title
NSSDate releaseDate
NSSDate score
My UI is a simple UINavigationController which has a segmented control as it's title and UITableView to display the Movies setup in Interface Builder. The segmented control has 3 segments: Title, Opening Date, and Score (on RottenTomatoes). The data for the table view is currently provided by a NSMutableArray movies which is a property of the AppDelegate.
I know that I can register target actions using the following code, but I am unsure of how to sort the UITableView data at this point:
[segmentedControl addTarget:self action:#selector(action:) forControlEvents:UIControlEventValueChanged];
How and where do I resort the UITableView whenever the UISegmentedControl selected segment changes?
Also, you can sort the data with any of the sortArrayUsingxxx methods in NSArray.
You can put some logic in the data source's tableView:cellForRowAtPath: method to check the current value of the UISegmentedControl and change the cell returned for each row as appropriate. Then, whenever the value of the segmented control changes, all you have to do is call
[tableView reloadData];
and you're all set.
I have a segment control that can order/filter items in three different ways - because the number of items is different depending on the filter / order I use 3 different NSArray objects to hold the sorted lists.
So when I load up the data I put a version of it in the correct place in each array (or not in the array depending on the filter).
I have a call to get the array that uses the state of the segmented control to decide which array to return.
The method that calls an array is used in place of a normal array and this means all I have to do to change things when a segmented control is changed is call [tableView reloadData] and all is done for me.

How do I set a custom cell for non databound TableCells

I am happily able to set the styling of my tableviewcells using the cellForRowAtIndexPath delegate, but I want to set the background of all the nonpopulated cells which are still on the screen
hey, basically any cell which is part of your tableview belongs to a particular index and particular row
so incase you are not populating a particular section via data source - you can still get a reference to a cell in that indexPath by manually calling the cellForRowAtIndexPath delegate, and passing the section as well as row index
it returns you a cell. assign it to your private variable and edit it the way you want to.
Use the visibleCells method on your table view. Then do what you wish to the cells.
Alternately, you could call indexPathsForVisibleRows to get just the index paths. Then call cellForRowAtIndexPath: to get the cell corresponding to each index path.