What is difference between
[tableView deselectRowAtIndexPath:indexPath animated:NO];
and
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexpath];
[cell setSelected:NO];
???
In a UITableView a cell does not match a specific piece of your data. It can (and should most of the time) be reused and it is nil when not visible.
deselectRowAtIndexPath will set the indexPath as 'not selected' in your tableview, so when you scroll back and forth to that cell, it will stay unselected, because you told your tableview that whatever the cell you display at that indexPath it should be unselected.
With UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexpath];
[cell setSelected:NO]; you set the cell as unselected. However that cell can be used for other pieces of data, and it can even be nil if this indexPath is not displayed.
First one is programmatically deselecting the cell. So it will un-highlight the cell if the user has selected it already.
As for the second bit of code, I believe that is just a pointer or reference to one of the cells in your table view. You can use this code to edit a cell OUTSIDE of any of the table view delegate methods. So if you wanted to edit/update a label on one of your cells but from a random method (not a table view delegate method), then you could use that code to reference the label text property.
I think you should also check out the Apple Developer Library website. It explains all the different table view method/properties/etc in lots of detail:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableView_Class/
The concepts of "selected" is different for a tableview and for a cell. The tableview can have one or more rows selected that changes the state of the tableview, however changing the tableview cell selected state only affects its appearance and nothing else.
Related
So I got this method that I call on didSelectRowAtIndexPath:
- (void)selectTableViewRow:(int)row {
[[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:1]] setAccessoryType:UITableViewCellAccessoryNone];
[[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:1]] setAccessoryType:UITableViewCellAccessoryNone];
[[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:1]] setAccessoryType:UITableViewCellAccessoryNone];
[[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:row inSection:1]] setAccessoryType:UITableViewCellAccessoryCheckmark];
}
(It's only three cells so no for-loop)
It works perfectly fine. When a cell gets selected, there appears a checkmark and the others get removed. But when I call this method in viewDidLoad nothing changes graphicly.
Do I have to reload the table view after setAccessoryType?
This is because your tableView will reload its data after -viewDidLoad is completed. This means that your table view will call -tableView:cellForRowAtIndexPath: in your table view data source, and it will use whatever cell accessory is specified there.
You should specify your cell accessories in tableView:cellForRowAtIndexPath:
At viewDidLoad time, your cells won't get created until they're needed. You have to be careful here, as cellForRowAtIndexPath, if done properly can generate entirely new cells, and throw out ones you already created. You should move your code for setAccessoryType into your cellForRowAnIndexPath, and have it check to see if each cell should be selected based on a variable which is set to the currently selected row and compare it to the indexPath.row.
The issue is that iOS can toss and reuse cells. If you set cell 1's accessory view in your routine, it might get scrolled off the end, and reused elsewhere, say now as cell 7. So cell 7 has the checked accessory view, and cell 1 is off screen.
In other words, cellForRowAtIndexPath feeds cells to the tableView. It's up to you to set their contents correctly based on the indexPath you get called with, especially if you reuse the cell - you have to clear the accessory view or set it for every cell that's called.
I'm getting some weird behavior in my UITableViewController.
I've subclassed UITableViewCell and created by own "visited" property within it.
- (void)setVisited:(BOOL)visited animated:(BOOL)animated
{
[self setVisited:visited];
...
}
I set this property when I create the cell in tableView:cellForRowAtIndexPath: (the only place I create it) like below:
if (cell == nil) {
cell = [[ArticleListViewCell alloc] initWithReuseIdentifier:CellIdentifier art:art index:indexPath.row];
[cell setVisited:NO animated:NO];
}
Later, in tableView:didSelectRowAtIndexPath:, I set this property to YES:
ArticleListViewCell *cell = (ArticleListViewCell *) [tableView cellForRowAtIndexPath:indexPath];
[cell setVisited:YES animated:NO];
However, when I select a cell and then return to this UITableView, which currently has 10 cells, I find that not only has the cell I selected become "visited", but also another cell has as well. It's hard to explain, but if I select the 1st cell, the 7th also becomes visited, if I select the 2nd, the 8th also becomes visited, and so on. Does anyone know why this is, and how I should go about fixing it?
I've checked this question, but it doesn't seem to help much.
This is caused by cell reuse. You need to set visited every time, not just when you create the cell.
if (cell == nil) {
cell = [[ArticleListViewCell alloc] initWithReuseIdentifier:CellIdentifier art:art index:indexPath.row];
}
BOOL visited = ... // value for this indexPath
[cell setVisited:visited animated:NO];
And in your didSelectRow method you need to update some sort of data structure keeping track of which row has been visited. You use this data to set the value properly in the cellForRow method.
Do not use the cell to keep track of state. The cell is a view. Your data source needs to track the state.
I have a table view with multiple cells. When I click on one of the cell it navigates to the next view controller, but my problem is that I cannot select multiple cells.
Could any one please help me on this issue, I want to select two or more cells with two finger tap.
set by code if you set by programming
table.allowsMultipleSelection = YES;
and if you set in xib tick on allowsMultipleSelection
Just add button like checkbox and multiple choose like checkbox.
If you are implementing the tableview programatically then the better way is to create a custom cell which will have button (and obviously other UI components that you need to show in the table view cell) which will work as a checkbox and assign button.tag as indexPath.row which will help you to select multiple rows.
Take a look here --
Below code will go into cellForRowAtIndexPath
YourCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.button.tag = indexPath.row;
[cell.button addTarget:self action:#selector(multipleCheckAction:) forControlEvents:UIControlEventTouchUpInside];
return cell;
-(void)multipleCheckAction:(UIButton *)sender { //sender.tag will be equal to indexPath.row }
Happy Coding
Since cells are being reused, you need to set the accessory mark to on or off for every cell in the table in the cellForRowAtIndexPath table datasource method.
So the cell.accessoryType cell property should be specified in the cellForRowAtIndexPath and not the didSelectRowAtIndexPath delegate method.
In the didSelectRow, just keep track of the selected rows in an array, and set the cells accessory mark to none or checkmark in the cellForRowAtIndexPath depending on the array value.
I'm creating an app which contains a screen that shows a table view with custom cells. Each cell contains two labels and a subview, which further contains other subviews. I'm handling the click event on the cell to hide/show the subviews within the subview in the cell. How can I make it so that when I click on a single cell, the subview of all the cells will change?
It is like the Stock application in iPhone (using iOS 7), here is a screenshot:
As in the image above, when you click on any of the green box, all the boxes change to reflect the same type of value.
Please let me know if this approach is fine, or how this can be implemented.
There are a couple ways of doing this. The first that comes to mind would be to handle the different states within the UITableViewCell subclass, and just reload the visible cells:
[self.tableView reloadRowsAtIndexPaths:[self.tableView indexPathsForVisibleRows] withRowAnimation:UITableViewRowAnimationAutomatic];
If you're looking for more control over the process though, this process could also be achieved by changing the state future cells should load into, and then calling a method on every visible cell. This would provide you with an easy way to have complete control over how the contents of the cell update.
// Change flag for cell state then...
for (NSIndexPath *indexPath in [self.tableView indexPathsForVisibleRows]) {
if (condition) {
MyCellSubclass *cell = (MyCellSubclass *)[self.tableView cellForRowAtIndexPath:indexPath];
[cell someMethodWithArg:(id)state];
}
}
To do something as in Stock app you should handle two method cellForRowAtIndexPath: and click action method.
In cellForRowAtIndexPath: you should do the check which cell/button was pressed and display value base on it:
//Pseudo code
//cellForRowAtIndexPath
if (cellNo3Pressed)
{
//set up text with the right value.
}
else if (otherCell)
{
//set up text with the right value.
}
This will handle the cell which are not visible on the screen.
The next action method should handle nice animation on all of the visible cell:
NSArray *paths = [tableView indexPathsForVisibleRows];
for (NSIndexPath *path in paths)
{
UITableViewCell *cell = (UITableViewCell *)[self.tableView cellForRowAtIndexPath:path];
//Animate changes for cell
}
It's My first time to post a question, thank you for you all in advanced.
Now, i want to implement a default style grouped UITableView contains multiple group of data. for each row, there will be a detail Disclosure button as accessoryType icon. when people click on the disclosure button, i want the Cell expand with detail info for the selected row.
i was trying to fulfill this task by add a customized cell to selected row, however, it was very complex. So currently, i am trying to finish this task by reload a specific row with Customized cell xib. i knew there is a delegate method for reloadRowsAtIndexPaths. but can i use this to reload a specific cell? Thanks
please suggest!
Great Thanks
Have you tried something like this:
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.row == mySpecialSelectedCell)
{
//Load all your custom stuff here
}
else
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CellIdentifier];
}
if (cell == nil)
{
}
return cell;
}
You would have to get the cell's indexPath when you click the expand button.
Or you could look at this answer. And then, like the code above, just load that one cell that you have specified with that NIB and load the rest the way you would normally.
You can implement the tableview delegate methods to set the height for the cell which needs to expand. Add some condition check in heightForRow method and when user taps on button, change the condition to increase the height. When table is reloading it will call this method and will reload cell with bigger height.