iOS UITest : How to find UITableViewCell's AccessoryView? - ios

Hello I'm learning UITests now
I have a question
how can detect accessoryView's tap on the tableViewCell?? in UITest
below is my tableViewCell
I want detect detail closure accesorry view's tap
like this
app.tables.cells.buttons["FTCellAccesoryIdentifier"].tap()
but accesorry is a subclass of UIView
so i allocate accisibility identifier key in cellForRows function
cell.accessoryView?.accessibilityIdentifier ="FTCellAccesoryIdentifier"
and my test function is
i try
app.tables.cells.elementBoundByIndex(lastCellIndex).otherElements.elementMatchingType(.Any, identifier: "FTCellAccesoryIdentifier").tap()
but not work
is possible to tap cell's accesoryView in UITests?

TL;DR
Regarding...
is possible to tap cell's accesoryView in UITests?
... Yes.
But you have to use the default accessibility identifier for that.
For example, for a cell like this one:
Tapping the Detail Disclosure button during a UI test ("More Info" is the key here):
XCUIApplication().tables.buttons["More Info, Title"].tap()
Tapping the cell itself during a UI test:
XCUIApplication().tables.staticTexts["Title"].tap()
Long story:
There is no way to change the default accessibility identifier of the Detail Disclosure. From Apple:
Note: If your table cells contain any of the standard table-view elements, such as the disclosure indicator, detail disclosure button,
or delete control, you do not have to do anything to make these
elements accessible. If, however, your table cells include other types
of controls, such as a switch or a slider, you need to make sure that
these elements are appropriately accessible.
At the time you try to set the accessibility identifier/label of the Detail Disclosure in cellForRow, cell.accessoryView is nil. Why? Again, from Apple:
accessoryView
Discussion
If the value of this property is not nil, the UITableViewCell class
uses the given view for the accessory view in the table view’s normal
(default) state; it ignores the value of the accessoryType property.
The provided accessory view can be a framework-provided control or
label or a custom view. The accessory view appears in the the right
side of the cell.
The accessory view will be nil until you define them. :/
You would need to provide your "own" Detail Disclosure (e.g.: a customized UIView) if you really want to set a custom identifier for it. For example (to illustrate):
cell.accessoryView = UIView(frame: CGRectMake(0, 0, 20, 20))
cell.accessoryView?.backgroundColor = UIColor.blueColor()
cell.accessoryView?.accessibilityIdentifier = "FTCellAccesoryIdentifier"

You should use accessoryButtonTappedForRowWithIndexPath delegate method to handle click on accessoryView.
Then by indexPath parameter of method you can know which cell it is!
Hope this will help :)

Related

UIButton default tap animation inside UITableViewCell

I have a few UIButtons inside UITableViewCells, and all of them are missing default tap animation, however if I long press - animation works. I've found some solutions, like setting type to .system, showsTouchOnHighlight = true, but none of them have helped. What is the problem here?
It's not a "problem" - it's by design.
When you have an object such as a button in a table view or scroll view or collection view, and you "touch" it, the system needs to know whether you are tapping the button or if you want to touch-and-drag to scroll the view that contains the button.
So, the table view (really, the "scroll view part" of the table view), waits to see if you drag your finger or not before it performs any actions.
If you want the button to respond immediately to a touch, you need to set
delaysContentTouches = false
on the containing scroll view(s).
If you search for uibutton inside uitableviewcell delaysContentTouches you should find plenty of discussion on this topic, and various approaches to change the default behavior.
For this problem you can add extension to UIButton and override some methods.
You can check my answer here

KIF cannot tap UIButton inside UITableViewCell if it's its UITableView's only one

I am having trouble automating tapping on an UIButton that is embedded inside a UITableViewCell if that cell is the table's only one. This is in the context of UI automation with KIF.
Here my relavant call:
[tester tapViewWithAccessibilityLabel: #"LABEL"
traits: UIAccessibilityTraitButton];
// trait only specified for 2nd case below
Here is what I am observing:
If I put the accessibility label on the UITableViewCell KIF's KIFUITestActor - waitForAccessibilityElement:view:withLabel:traits:tappable: returns the UITableView, not the cell. Somehow the table seems to inherit its only child's accessibility label and lets KIF encounter it first during its recursive search.
If I put the accessibility label on the UIButton instead, KIF finds it but determines that is is not tappable (i.e. UIView-KIFAdditions -tappablePointInRect: returns NO), presumably because its mainly transparent between the thin font lines for the button's label (the tap goes to a UITableViewCellContentView instead).
A workaround might be tapping on the row by it's NSIndexPath but maybe there is still a better way to overcome the described hurdles I am facing. So how could I instruct KIF to tap a button like this with a call to tapView...?
If you are making cell in code, make sure your button is added to cell.contentView.
If you are loading cell from xib, try to send contentView to back of view hierarchy (I have not found any downsides yet for doing it) with:
[self sendSubviewToBack:self.contentView];
This is just to confirm that this workaround is applicable:
[tester tapRowAtIndexPath: [NSIndexPath indexPathForRow: 0 inSection: 0]
inTableViewWithAccessibilityIdentifier: #"IDENTIFIER"];
The "good" solution should be something like this:
UITableViewCell *cell = [tester waitForCellAtIndexPath:indexPath inTableViewWithAccessibilityIdentifier:tableAccessibilityIdentifier];
UIAccessibilityElement *element = [cell accessibilityElementWithLabel:accessibilityLabel traits:UIAccessibilityTraitButton];
[tester tapAccessibilityElement:element inView:cell];
Unfortunately it doesn't work as expected. Sometimes the element is a UIAccessibilityElementMockView and tapping it in step 3 leads means just tapping the underlying cell. Naturally the results will not be as expected.
I've managed to finally work around that by doing something more along the lines of:
MyCustomCellClass *cell = (MyCustomCellClass *)[self waitForCellAtIndexPath:indexPath inTableViewWithAccessibilityIdentifier:tableAccessibilityIdentifier];
[cell.buttonOutlet sendActionsForControlEvents:UIControlEventTouchUpInside];
Note that this means
relying less on UI interaction
having a custom class
having an outlet to the button
But hey, KIF isn't supported by Apple so it sometimes, you know, breaks :)

iOS - change view (UICollectionViewCell) to disabled status

I have a UICollectionView and I want some of my cells to be disabled. That means I want the cell to look a bit greyer (to have a disabled feeling), and I want the user to not be able to click on the cell.
I know I can use the alpha parameter and set it to something like 0.7, but this gets disabled while moving the cells around, and also it doesn't look grey enough. So I'm looking for another option to do it.
For controlling the tapping on a cell, I know I can use collectionView:didSelectItemAtIndexPath: and check for the indexPath. But I was wondering if there's another option for disabling a cell, like there is for disabling a UIButton: myButton.enabled = NO.
You can always set userInteractionEnabled to NO for the UICollectionViewCell and any taps inside it will be ignored.
Your problem with the alpha sound like you need to do some more work in prepareForReuse, or implement prepareForReuse in your custom cell class if you have not already done so.

iOS: Making only one UIView to respond

I have several UIViews (CollectionView, TextField, etc) in my ViewController. If the user presses any item in the collectionview, a new collectionview (smaller) is to be shown from the bottom.When the new collectionView is being shown, I want only this view to respond to touch events. If the user taps outside this view, it should be taken off the viewController. The functionality is similar to PopOverController. I am using
[subCollectionView becomeFirstResponder]
but the other views are also responding to touch events.
I wish I could put the question more clearly, Let me know if it is not clear.
Thx!
No need of setting firstResponder of a UIView.
All you need to do is
create a view named bottomAnimateView(which will come from bottm) of size =
self.view.frame and background color as clear color.
add a UICollectionView over it.
3.Add UITapgesture over bottomAnimateView and do the stuff of removing or hidding it from superView.
Refer the attachment .Which might help you.

UIButton subview in UICollectionViewCell not changing control state

I have a UICollectionView where each UICollectionViewCell has a UIButton as a subview. The UIButtons respond to taps no problem (their targets get fired), but the button itself does not change to the selected state (no change in look and feel of the button). I have a hunch it's because of the UICollectionViewCell not properly forwarding its touch events to the button, but I'm not sure. Even if that's so, how do I set things up so that the button's state changes properly in this scenario?
The UIScrollview (and thus UICollectionView too) has a property called delaysContentTouches, by default it is set to YES, change this to NO and your button should highlight like it is supposed to.
If i may suggest an alternative, the UICollectionView has an awesome delegate method called
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { }
which could handle the click to that cell... if you are looking for specific events to happen like seeing an image change to the state of the button, you could hard code that in... when they press the button do one thing, when they release the button do another thing....
according to the documentation as well
UIControlStateSelected
Selected state of a control. For many controls, this state has no effect on behavior or appearance. But other subclasses (for example, the UISegmentedControl class) may have different appearance depending on their selected state. You can retrieve and set this value through the selected property.
in laymens terms.. for a UIButton the "Selected State" does nothing...
if the the button is suppose to dim when it's clicked and it's not doing that, then you may have to do that programmatically if, but i'm not exactly sure what you are trying to do...
the dimming feature is with in the highlighted state
UIControlStateHighlighted
Highlighted state of a control. A control enters this state when a touch enters and exits during tracking and when there is a touch up event. You can retrieve and set this value through the highlighted property.
in laymens terms, you touch the button it's highlighted
to see if the button is changing states properly you can do something like this
[button addTarget:self action:#selector(functionToCall:) forControlEvents:UIControlEventAllTouchEvents];
NSLog(#"Selected: %i", button.selected);
NSLog(#"Highlighted: %i", button.highlighted);
NSLog(#"Normal State or not: %i", button.state);
the "functionToCall will be called when any type of touch even happens to the button and with in that function you could have those 3 NSLogs which will print to your console the different UIControlState values, this will show that the button is working properly and show that it may be a UIViewCollection error, if it's the UICollectionView... then you will have to programmatically dim the button :3
hope this helps !

Resources