I have a custom UITableViewCell on my iPhone app for which I have a custom setSelected:animated method. My app works perfectly on iPhone, however, I started to port my app to iPad. I've copied the exact same storyboard, haven't changed anything, but now my setSelected:animated method is called twice (with the same parameters) when I select my cell. I could "handle" this case by checking if iPad etc. but it would be a bad practice. What could be the reason that it's called once on iPhone but twice on iPad? (both iOS 7.0.3) The table view's properties are exactly the same (I've copied the iPhone storyboard file).
Here is the relevant code:
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
isSelected = selected;
[self setNeedsDisplay];
if(selected){
SocialMatchAppDelegate *del = (SocialMatchAppDelegate*)[UIApplication sharedApplication].delegate;
del.selectedUser = self.user;
[del.resultViewController performSegueWithIdentifier:#"viewProfile" sender:self];
}
}
I suppose this is a normal behavior if you're using iPad.
In order to stop getting multiple "setSelected:YES" or multiple "setSelected:NO", all you have to do is this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
Now, 1 click on any cell gives you:
1 entry of setSelected:YES animated:NO
1 entry of tableView: didSelectRowAtIndexPath:
1 entry of setSelected:NO animated:YES
Where did - (void)setSelected:(BOOL)selected call in your source?
If it is in - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
Using this instead
[tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone];
Related
sorry, I wanna to know that apple's underlying code implementation
In storyboards you can set identifier of each of the cells you put inside the table view by setting any text to Identifier field:
The text in your code must be exactly the same, case sensitive to use it.
There are also ways of doing this programmatically to register a cell on table view before using it (setting it in viewDidLoad should be enough).
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerClass:[MyTableViewCell class] forCellReuseIdentifier:#"MyTableViewCellIdentifier"];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyTableViewCell *myCell = [tableView dequeueReusableCellWithIdentifier:#"MyTableViewCellIdentifier"];
return myCell;
}
I've got a UITableView which is automatically set up for multiple selection in Edit Mode using the following lines in viewDidLoad:
self.tableView.allowsMultipleSelectionDuringEditing = YES;
[self setEditing:YES animated:YES];
However, I'd like to indicate that a row was selected by changing its background color, rather than by the checkmarks which automatically appear along the left of each row. (For example, the ones that appear when editing the email list in the Mail app, or being discussed in this SO question.) I've got it working for the most part, except that I can't get those checkboxes, which are automatically created as part of putting the UITableView into Edit Mode, to go away.
Below is the code I'm working with:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return _Hierachy.cellCount;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *testCell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if(testCell == nil) {
testCell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
[[testCell textLabel] setText:#"Test Cell"];
return testCell;
}
Those are the only UITableView methods I've got so far, so everything else should be default behavior.
Does anyone know how to hide those checkmarks along the left, in Edit Mode? I've seen many questions about checkmarks in the accessory portion of the cell, but as I understand it, this is a different thing. I've also seen people talk about the tableView:didSelectRowAtIndexPath: method, but these checkmarks are created when the table enters Edit mode and dismissed when the user taps "Done," so that method doesn't seem related.
The closest I've come is finding this method:
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath{
return NO;
}
But that just prevents the cell's content from indenting to make room for the checkmarks. The checkmarks still appear.
Surely there's a way to hide those checkmarks, and still allow multiple selection in Edit Mode? Or are those checkmarks seriously mandatory behavior for a UITableView in Edit Mode with Multiple Selection enabled?
EDIT: I am (reluctantly) open to answers that are somewhat hack-y, like moving the frame of the checkmarks until it's off the screen. This app is for internal use, and won't need to be approved for the App Store. But given that the checkmarks are created automatically when the UITableView moves into Edit Mode, I don't even know how to get them as objects to alter. Any help would be appreciated!
You'll have to subclass your UITableViewCell and override the (void)setEditing:animated: method like this:
#import "MyCustomCell.h"
#implementation MyCustomCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)setSelectedBackgroundView:(UIView *)selectedBackgroundView
{
//Cell Selected Color: CLEAR
[super setSelectedBackgroundView:selectedBackgroundView];
}
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
//Cell Edit Mode NO Indent & Selected Color: CLEAR
[super setEditing:NO animated:animated];
[self setNeedsLayout];
}
#end
After you do that, go to Inteface Builder and make your cell part of the class MyCustomCell.
After you make your cell part of MyCustomCell class in IB, import MyCustomCell.h in your UITableViewController and modify the following in your code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyCustomCell *testCell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if(testCell == nil) {
testCell = [[MyCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
[[testCell textLabel] setText:#"Test Cell"];
return testCell;
}
UPDATE:
You could also do the following in your TableView's tableView:editingStyleForRowAtIndexPath:
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleNone;
}
But you will get your cell indented. To remove that indent you'll have to subclass the Cell.
You should be good to go after doing this! I've just tested it and it works the way you want it!
Here is the most simple solution for multiple selection with no checkmarks:
- (BOOL)tableView:(UITableView*)tableView canEditRowAtIndexPath:(NSIndexPath*)indexPath {
return NO;
}
This will cause the cells to be selected using the default selection style (gray or using your custom selection background), and no checkmarks will appear.
A word on whatever solution you pick. Users expect a consistent experience across multiple applications, and these checkmarks are part of this consistency. Make sure to have a good reason to change a normal OS look and feel.
here is how to achieve:
swipe to delete works
you don't see the checkbox, delete item or anything else on the left of the cell when in editing mode
Cell indentation still works normally (you can turn this off if you want)
(bonus) Support multiple selection
so - in your UITableViewDelegate
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (self.isEditing)
{
return UITableViewCellEditingStyleNone;
}
else
{
return UITableViewCellEditingStyleDelete;
}
}
- (void)tableView:(UITableView *)aTableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
(do stuff)
}
you also need to configure your UITableView
self.table.allowsMultipleSelectionDuringEditing=NO;
now if you actually do want multiple selection;
self.table.allowsSelectionDuringEditing=YES;
then manage the selected cells yourself.
I put a custom checkbox in my UITableViewCell subclass, and I also change the value in response to
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
The questioner wants to indicate selection with the background colour - that part should be straightforward.
My UITableView shows answers for questions.
To switch questions I apply CATransition to tableView and call reloadData method.
In case if user did select one row, went to another question and then returned back to the first question, I want the chosen answer to be selected.
I call
[tableView selectRowAtIndexPath:indexPath
animated:YES
scrollPosition:UITableViewScrollPositionNone];
in delegate method
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
But when answers appear after reloading UITableView, there are no selected cells. If I move cell out of the screen and then move it back, it becomes selected.
you need to implement following UITableView delegate method to perform any action on selection of cell
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// [self doSomethingWithRowAtIndexPath:indexPath];
// write your action on cell here
}
How can I deselect a cell when returning to a view?
I have an orange down state which is applied to a cell when selected - the cell navigates to a modal view when clicked - when i click back button the cell is still selected.
I have tried applying this code -
[tableView deselectRowAtIndexPath:indexPath animated:YES];
to my cellForRowAtIndexPath method - but it doesn't do anything!
Update - Having done a bit of research - It appears Ive missed some valuable information out of this question! - my table view is a UITableView embedded in a View Controller - not a UITableViewController - so it sounds like it doesnt have the available methods which are required for the suggestions so far..
You could use UITableViewController's clearsSelectionOnViewWillAppear property.
You should not call deselectRowAtIndexPath in cellForRowAtIndexPath method.
you can do this in viewWillAppear
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear: animated];
NSIndexPath *selectedIndexPath = [tableViewObj indexPathForSelectedRow];
if (selectedIndexPath != nil) {
[tableViewObj deselectRowAtIndexPath:selectedIndexPath animated:YES];
}
}
Or you can write in didSelectRowAtIndexPath as well
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath: indexPath animated:YES];
}
This is the right approach
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath: indexPath animated:NO]; // first line in this method
// rest of code
}
I am developing universal iOS app and try to achieve popover.
I have tried WYPopoverController and FPPopover but those 2 does the same issue.
I have simple UITableViewController having 10 cells putting a static text on each cell (just for a test).
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 10;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
UILabel *label = (UILabel *) [cell viewWithTag:1];
[label setText:#"test"];
return cell;
}
and try to show this in popover.
Sample code to apply FPPopover is
- (IBAction)test:(id)sender {
PopOverTableViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"PopOverTableViewController"];
FPPopoverController *popOver = [[FPPopoverController alloc] initWithViewController:vc];
[popOver presentPopoverFromView:sender];
}
This shows text in 10 cells at a button tap but once I scroll inside of tableview,
the texts disappear and non of tableview data source methods are called afterwards.
It happened for both WYPopoverController and FPPopover so I am assuming there is something wrong in my side.
However, I could not figure out where I went wrong.
I appreciate your help on this.
Thank you guys for answering my question.
I solved myself. It was due to having FPPopoverController as in local variable. I needed to put as instance variable with strong property, otherwise the controller is deallocated by ARC. That made a popover frame is still visible but table view content inside of popover is dismissed.
I am not sure what FFPopoverController does but in case of a normal popover controller you can use popover delegate method "popoverControllerShouldDismissPopover" to restrict the disappearance of a popover like following:
-(BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController {
return NO;
}
Surely, you need to declare UIPopoverControllerDelegate to the .h file of your view controller and set the "delegate" property of the popover controller to "self", for the above method to work.