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.
Related
As we know, UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:1]];method is invalid after the cell is out of our sight. (it's been put to the pool of reusable cells by system) So how do we track the information inside this cell?
I created another cell variable to point to it.In method -(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPathI make _trackMarkCell = cell; trackMarkCell is a property of current controller. This way I can always get the information of the cell. But I feel this way is not that smart, is there any better solution?
Thanks.
So, basically , UITableviewCell is just a view, that is used to display the content in UITableView so from the method -(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath you can crate a new cell or if the cell is already in the pool you can reuse it
come to your question, with the information i mentioned above, the cell holds the information that is used to display on tableview so u just no need to worry about the cell, but the data what you are displayed in the cell. u just keep track of the data and while updating the cell, clear all the information of the cell (which is crated newly or reused from the pool) before using it. for example
lets say suppose u are displaying the image in the cell, but after some time, image in the cell which is changed, in this case u just change the image which is present the datasource not in the cell, if u are using the images array to display the images in the cell,
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kMenuTableCellReuseId];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kMenuTableCellReuseId];
}
//hear clear all the info present in the cell
//no need of this also u can directly update the cell, but for clarity i mentioned this
cell.myImageView.image = nil;
//just load the cell with new data
cell.myImageView.image = [dataSource objectAtIndex:indexPath.row];
//.... other code
return cell;
}
one more thing using the another cell to keep track of the cell which is present in the pool which might give u different information of other cell. or that cell might be deallocate. so just keep track of the data not the table view cell.
Not sure how you're populating your cells, but if you're feeding the cells via an array of model objects, you'd have access to all your data within that array. You could reference the object with the information you're seeking based on the index within the array (eg. - array[3], where '3' is the index of the object desired)
So how do we track the information inside this cell?
You just don't. Cells don't store information. Cells display information from a data source. You store the data in arrays or Core Data or on a server or anywhere else. Then you just display it in the cells.
What you can do is, you can get data from the cell and put in your collection in UITableViewCell's prepareForReuse method: this will be called before the cell is reused.
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.
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];
}
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.
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.