I am using a custom class which is subclassing UITableViewCell. Now, when tableview goes in edit mode, I adjust the UIComponents on the cell inside layoutSubviews of my custom class. Now, when user tap on the "-" button the layoutSubviews get called once again and the UIComponents on the cell again repositions themselves which causes a weird UI flicker. I tried with below code in layoutSubviews but then UIComponents on the cell does not reposition themselves when user tap on edit and table comes in edit mode. Is there any graceful way to handle this.
if (self.editingStyle == UITableViewCellEditingStyleDelete) {
return;
}
Ok. Found this property which is set when user tap on the - button to show the delete button:
self.showingDeleteConfirmation
Related
I've been trying to create table view cells each with a UIImageView serving as a background for them. However, when I tap on each cell the table view will not register the click and will not transition to the view controller I have hooked up, even while I'm using the didSelectRowAtIndexPath function.
I realize it's probably an issue with the ImageView obstructing the table views ability to register the cell tap. The cells will transition however when I drag my finger/mouse on it from left to right, just not on taps. I tried to use a Tap Gesture Recognizer on the Image View however it only worked for the cell at the very top and not all of them. How do I tackle this issue?
Here is an image of the table view cells so you have an idea of what I'm working with: http://imgur.com/a/Ku4uD. Thank you!
If you uncheck User Interaction Enabled on your Image View, the problem should be solved. When running into a problem always check the user interaction of the most child view and work your way up.
One trick I have also learned is to create a subclass of a child and override touchesShouldCancel like so:
override func touchesShouldCancel(in view: UIView) -> Bool {
print("touchesShouldCancel")
//Run extra code that you want when the user selects this view
//then still retrieve the tap by its parent.
return false
}
I am unsure of exactly what your problem is, but I would delete whatever segue that you have, add a new one by dragging from the yellow circle on the left side of the center portion of the top of your tableView ViewController inside the storyboard, to the viewController that you desire it to segue to. Give the segue an appropriate identifier, and then inside your tableView class under tableView didSelectRow add performSegue(withIdentifier: "ChosenIdentifier", sender: indexPath)
Then in prepare forSegue add in:
if let vc = sender.destination as? TheViewControllerYouAreSegueingTo {
if let indexPath = sender as? IndexPath {
vc.variableIdentifyingWhatCellWasClicked = indexPath.row
}
}
with whatever adjustment is needed to meet your specific needs.
I have a tableView with two UITextViews. The user can add as many cells as they want by tapping on a "+" button. The tableView starts out with one row (cell). Lets say the user adds some information to the two textViews and then taps the plus button and scrolls to get to it. I call this function to dismiss the keyboard when a user scrolls so it isn't in the way:
override func scrollViewDidScroll(scrollView: UIScrollView) {
self.view.endEditing(true)
}
Now, the keyboard disappears and the user goes to tap on the second row's text field. The tableView jumps up (I think to accommodate the keyboard), but the textField can't be edited (no cursor and keyboard doesn't appear). If I go back up to the first row (row 0), the keyboard appears and I can edit the textView. Why is this happening?
There is a property on scrollView subclasses (e.g TableViews)
tableView.keyboardDismissMode = .OnDrag
Once the user begins a descending drag it dismisses the keyboard
scrollViewDidScroll calls everytime the tableview moves, so when "The tableView jumps up (I think to accommodate the keyboard)" it also calls and close the keyboard. You should add there some confines or put endEditing code in the other place.
Pressing the button quickly and not holding for a short time, will not highlight the button.
Different from a UIButton on a common UIView.
Like the head photo in official Twitter client got same issue.
Instagram client seems solved this, all buttons works fine.
Find same question here:
Why doesn't UIButton showsTouchWhenHighlighted work when the button is on a UITableViewCell?
But I still don't know how to fix it.
Well... a UITableView is a subclass of UIScrollView and the UIScrollView class is known to eat touches for it's own purpose.
When it realizes the touch was not meant for it, it passes it to it's immediate subview.
This feature is the delaysContentTouches property (which by default is YES).
Which is why, the UIButton shows it's highlighted state only after a extended touch because the touch event was with the UITableView for a short while until it determined whether the touch was meant for scrolling or swiping the cell and on realizing the touch was for neither, it immediately passes the touch event to the subView directly below it.
In case of a quick-tap, the button's highlighted state is bypassed due to this delay and the target selector method is called directly.
To show the highlighted state of the button in a UITableView (just as it would on a UIView) do:
For iOS7+:
In -viewDidLoad or anywhere appropriate do:
[yourTableViewObject setDelaysContentTouches:NO];
Also... The cell.subviews has a class UITableViewCellScrollView which apparently is another scrollView and we need to disable the delaysContentTouches property of this class as well.
So... in the -cellForRowAtIndexPath: method (just before return cell;) do:
NSArray *test = cell.subviews;
for (UIView *currentView in cell.subviews) {
if ([NSStringFromClass([currentView class]) isEqualToString:#"UITableViewCellScrollView"]) {
UIScrollView *svTemp = (UIScrollView *) currentView;
[svTemp setDelaysContentTouches:NO];
break;
}
}
For iOS 6-:
In iOS6, the cell.subviews has a UITableViewCellContentView class which is not a scrollView subclass and so all it takes is setting one parameter for the tableView alone.
So, in -viewDidLoad or anywhere appropriate, this is all that you need:
[yourTableViewObject setDelaysContentTouches:NO];
PS: By doing this, it will mess up with the scrolling of the tableView so use your better judgement.
I have a UITableView with a custom UITableCellView subclass. I want to show one of the rows as active or selected. The controls in my cell have their own gestures, but I have area on the right where I can do the selection. I had (naively) thought I could just indicate I wanted a checkmark style accessory but Apple's docs say
This control does not track touches. The delegate of the table view
can manage check marks in a section of rows (possibly limiting the
check mark to one row of the section) in its
tableView:didSelectRowAtIndexPath: method.
I'm not sure how to interpret that, but I put the tableView:didSelectRowAtIndexPath: method in my delegate, and it never fires. Regardless of where I touch my cell (on the part where there are touchable controls or not). So I'm curious why that doesn't work? I also noticed that regardless of how I set the selected property on the cells, the checkmark always shows on, so I don't think it's really meant to be used a selection indicator.
But I'm actually kind of OK with that. I don't really want a checkmark, I'd rather do something like mail does when it does multi select on the left side, the radio-button-esque style circles. Which then leads me to a quandary about how to proceed. Should I just add a button control to the right side, manipulate the images appropriately in my custom cell subclass? Do I mess with the background image of the button in that case? Or just the image? And since selecting one needs to deselect the others, what's the best way to connect this to the table view delegate, rather than the subclass? Or should I make a custom NSView subclass?
UPDATE
I removed the accessory. I added an UIImageView to show selection state. Because the sub control in my cell uses a hold gesture, the selection tap makes it through just about everywhere for the cell. I synchronize the visual selection state using the following method:
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
self.selectionView.image = self.selected ? [UIImage imageNamed: #"selected"] : [UIImage imageNamed: #"not_selected"];
}
To my custom controller, I added the following method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[Site setCurrent: self.allSites[indexPath.row]];
[[Site current] pullValves];
}
It finally donned on me that that the first method was for updating the visual state, but not for responding to the users intent, that belongs in the second method. The first fires at various times, but the second applies when the user actually does the tap.
Finally, I had to programmatically set
self.clearsSelectionOnViewWillAppear= NO;
Not matter what I set in the storyboard, that value was YES, so returning to the list was clearing my selection.
You're adding a gesture to each of the cells you create? I would back that out of there and create a gesture on the main controller which holds your tableview (not the individual cells).
Add this to your main controller so the controller can handle the gestures accordingly.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
If you need to track the cell that was touched (say, for a panning gesture), you can grab the index path given the gesture recognizer.
CGPoint p = [recognizer locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:p];
From there, we go back to your goal: tracking your active cell. tableView:didSelectRowAtIndexPath needs to be hit (hopefully the steps above help here). Store some sort of identifier of the item you need to keep selected. When tableView:willDisplayCell:forRowAtIndexPath is called you can trigger the selection state.
I'm preparing a UITableView with a custom prototype cell having a UISwitch widget on the right side, and I'd like to let my users be able to delete rows.
Everything is fine with that, except the fact that when the delete button shows up it overlaps to the UISwitch, this way:
Is it possible to have the UISwitch shifting left when the delete button appears?
Epilogue
I've decided for brevity to not shift my UISwitch position when "delete" button appears, but to make it disappear, bringing it back when the "delete" button is gone.
So, according to #geo suggestion (thank you), I've managed it out (quite simply) this way:
In my UITableViewCell' subclass .m file:
- (void)willTransitionToState:(UITableViewCellStateMask)state
{
[super willTransitionToState:state];
if (state & UITableViewCellStateShowingDeleteConfirmationMask) {
activationSwitch.hidden = YES;
}
else {
activationSwitch.hidden = NO;
}
}
I hit a very similar problem and fixed it. You need the right autoresizing mask (assuming not doing auto layout here) for your UI elements in your custom tableview cell in Interface Builder.
In my case, I needed to add the Left constraint (see that little autoresizing picture/animation in the Size Inspector, View section) for each of my UI elements.
Add a Left "bar", and you should be good.
Override the Methode
-(void)willTransitionToState:(UITableViewCellStateMask)state
-> UITableViewCellStateShowingDeleteConfirmationMask
of your custom Cell and do there your customizing :)