Table view cells do not lose highlight on touch up - objective-c

When I click a cell it selects, but it stays blue on touch up. I want the blue highlight to leave on touch up (but it's important that it highlights in the first place).
This last answer in this post mentions something about willSelectRowAtIndexPath:, but I can't figure out how to use that to do what I want. Also, I do need didSelectRowAtIndexPath: to still be called, I just want the cell to unhighlight on touch-up.

Use the following where appropriate:
[tableView deselectRowAtIndexPath:indexPath animated:YES];
e.g. in didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
This will deselect the row at the specified index path.
You could also be interested in clearsSelectionOnViewWillAppear property in UITableViewController. If this property is set to yes then the controller clears the selection when the table appears. In default it set to YES.
Reference.

Related

How to tell if a UITableView's cell is visible on the screen

I'm writing an Objective-C app for iOS 8. I was wondering if anyone knows how to tell if a UITableViewCell in a UITableView is on-screen.
For example, if the y value of the UITableView's contentOffset is 0 (meaning that the UITableView is scrolled to the top) and I programmatically select row 2, I don't want to scroll at all because row 2 is already visible (assuming that the UITableView is large enough to show at least 3 rows). However, if I programmatically select row 10 (which is off screen), I want to programmatically scroll to that row.
This is the code I use to scroll to the selected row:
[self.tableView scrollToRowAtIndexPath:[_tableView indexPathForSelectedRow]
atScrollPosition:UITableViewScrollPositionMiddle
animated:NO];
Now, I just need to nest that code inside an if-statement that checks to see if the cell at the currently-selected row is fully visible on-screen.
Any suggestions?
Since you want the selected row to be visible with the least amount of movement, use the method made just for that:
[self.tableView scrollToNearestSelectedRowAtScrollPosition: UITableViewScrollPositionNone animated:YES];
From the docs for UITableViewScrollPositionNone:
The table view scrolls the row of interest to be fully visible with a minimum of movement. If the row is already fully visible, no scrolling occurs. For example, if the row is above the visible area, the behavior is identical to that specified by UITableViewScrollPositionTop. This is the default.
Try this,
NSIndexPath *path = [tableView indexPathForCell:tableView.visibleCells.firstObject];
[self.tableView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionNone animated:YES];
There is no way to ask to the tableview if a view is shown at specific time.
What you can do is to be delegate for this tableview and implement this methods:
- (void)tableView:(UITableView *)tableView
willDisplayCell:(UITableViewCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView *)tableView
didEndDisplayingCell:(UITableViewCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath
You can implementing this methods track the uitableview showing at that moment.

Getting name of cell from indexPath / Swip Gesture

The Situation
I'd like to be able to get information about the title of a cell within a UITableView when the user swipes the cell (to display the "delete" button).
The Code
When the user swipes a cell in the UITableView, this method is fired:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath*)indexPath
The Problem
I need to be able to get the name of the cell the user "swiped" so that my iOS (Obj-C) app can do various operations, etc.
Everything Else
I know that the indexPath has something, but I can't get an NSString from it (which is what I need).
I was also thinking that a workaround such as using a gesture recognizer instead of the above method might be able to provide me with more information about the cell.
Any ideas as to how I can get the name of the cell when the user "swipes to edit / delete"?
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *text = cell.textLabel.text;
// do something with text
}
Please, how does your table work in the first place - you don't seem to understand the basic principles of it. You back your table up with a data model. YOU provide and construct the cells for each indexPath, so you should know how to access the data in your model using that swiped indexPath, no?
Of course you could also ask the tableView delegate (yourself) for the swiped cell by calling tableView:cellForRowAtIndexPath: and then check the labels on that cell.
Have a look at the implementation of your tabkeView:cellForRowAtIndexPath: method all your info of how to get the data should be there...
All in all it's pretty easy, if you provide some code you sure will get more hints.

Unexpected TableViewCell highlight delay

I'm trying create TableViewCells which mimic buttons. This means that on touch down, there should be a highlight effect and on touch up should trigger the standard selected state. This works as intended, but the problem is that there is a split second delay between touch down and the highlighted state appearing. Why is this? How can I make the highlight appear immediately on touch down without the delay?
Here's the code I'm using on my TableView delegate:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[[tableView cellForRowAtIndexPath:indexPath] setSelected:YES animated:NO];
// do something here
[[tableView cellForRowAtIndexPath:indexPath] setSelected:NO animated:NO];
}
I suppose I don't really understand your question as you've asked it. UITableViewCell already acts "like a button" when pressed in the sense of it highlighting. From the looks of your code, it really does nothing that the tableView doesn't do natively.
Basically, the reason you are seeing a delay is because the cell already highlights on touch, and what you are doing is setting Selected to YES, then NO, but the cell already does this, so it's kind of doing the same thing twice, once on it's own, then once forced — this is the reason for the delay you are seeing.
The only thing that should go in didSelectRowAtIndexPath: is the actions you want to happen when the button is pressed, NOT what you want the cell to do or how it should behave upon being touched. There are other delegate methods that would handle these behaviors.
If you are looking to change the highlight color of the cell, then see my question/answer here.
Update
By default, the UITableView code provided by Apple does not contain the deselect method. So when you select the cell it stays selected. To deselect the cell, add the following method to didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
/* The following will deselect the cell on touchUp */
[tableView deselectRowAtIndexPath:[tableView indexPathForSelectedRow] animated:YES];
}

Can I add a disclosure Button to only one cell in my UITableView?

I have a UITableView and I want to add a disclosure button to a cell but only when the cell is selected.
How can i do it?
Thanks
in tableView:didSelectRowAtIndexPath: save the indexPath to a member variable.
in tableview:cellForRowAtIndexPath: check, if the indexPath is the saved one and set cell.accessoryType
Do it in
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//bla bla bla
}
Remember to have a variable to remove the button from the previous selected cell
In the table view cell set the accessoryType or accessoryView property. You will want to do this in the -tableView:didSelectRowAtIndexPath: delegate method.
Doing it in didSelect means that the disclosureButton only appears after the user releases the selected cell. If you want ti to appear when the cell is highlighted, you need to subclass UITableViewCell and override setSelected: or setHighlighted:
However, the whole point of a disclosureButton is that the button can be pressed and does something different then simply selecting the cell. For that there is the disclosure indicator. The whole premise of making either of these show up only when the cell is highlighted/selected doesn't seem to serve any good UI design purpose in my opinion...but maybe for what you want it does make sense.

Search result of UISearchDisplayController has other cell layout and behaviour than searched table

I am using storyboarding. I have an UITableView with one prototype cell. This cell is of style "subtitle". I have added a segue from the cell to the detailed view. So when the user taps a cell it will open the corresponding editor... That all works great.
Now I added a UISearchDisplayController an a UISearchBar, implemented the delegates. That works very well.
But in the search result table the cells are of style "default" and are not tapable. What do I have to do to get a result table looking and behaving like the "unsearched" table?
I would like to contribute for answer #1 this is what I did and it worked for me
in the method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
instead of assigning the cell from the parameter tableView
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
assign it directly from the TableView on the view so you have to replace this
// UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
with this
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
Found the problem...
The method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
pulled the cell from the tableView, which is in the result case not the tableView from the storyboard but the resultTableView from the SearchDisplayController.
I now get the cell to display in both cases from the table view in the storyboard and now it works.
I've been using ios 7.0 and Xcode 5.0. I found that search display controller is using the same tableview layout as the delegate view controller. All you have to do is judge if the current tableview is the delegate view controller's tableview, or the search display controller's tableview. But remember to add the sentence
tableView.rowHeight = self.tableView.rowHeight;
in the following code snippet:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
if (tableView == self.searchDisplayController.searchResultsTableView)
{
tableView.rowHeight = self.tableView.rowHeight;//very important!
return [self.searchResults count];
}
else
{
...
return ...;
}
}
if you forget to implement that sentence, then the row of the table view of search display is only as high as a default row, which makes you think it doesn't look like the "unsearched" table.
There is a possible answer to this here. It may not work entirely for you, but as I explained, the UISearchDisplayController creates the table view.
Check the documentation and you can get a better understanding of it, but it states:
You initialize a search display controller with a search bar and a
view controller responsible for managing the original content to be
searched. When the user starts a search, the search display controller
is responsible for superimposing the search interface over the
original view controller’s view and showing the search results. The
results are displayed in a table view that’s created by the search
display controller. In addition to the original view controller, there
are logically four other roles. These are typically all played by the
same object, often the original view controller itself.
In my case UISearchDisplayController was using right cell type (custom) but height of cell was wrong so I had to use
(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
method to fix it.