Xcode7.3 UITest of Disclosure Indicator in a custom TableViewCell - ios

(Xcode 7.3.1, iOS9.3, Swift)
I'm struggling with setting up an UI Test in my assignment for what would seem to be a fairly standard and common use case.
I have a sub-classed UITableViewCell which contains a textField that does not fill the entire cell and has the Disclosure Indicator set. The user is able to type the data into textField by tapping on it, but if they tap outside the textField, but still in the cell, my app segues to another view. The project works fine and the child view receives the correct data from the cell's textField.
My Master-Detail app has UITableViews on both the Master and Detail views. My UI Test selects the first cell in the Master View, waits a little for the DV and then selects the second cell in the detail view, which is configured in accordance to my earlier description.
I am simulating a tap on the second cell using
tablesQuery.cells.elementBoundByIndex(1).tap()
However, the simulator interprets it as a tap in the textField, so no segue occurs. I have read SwiftyCruz's question and the given answers but his use case is a little different, as I'm not using a Detail Disclosure, also the accepted answer doesn't translate to my situation. In following ferunandu explanation, I have tried setting the Accessibility Label and Identifier on the Cell as well as a different string for the accessoryView?.accessibilityIdentifier. Though UI Test still doesn't work, ferunandu's snippet does change the disclosure indicator from > to a blue box.
Using a breakpoint, I've been querying the app object in the debug window trying to find the right control, but to no avail. I am able to find the textField using indices as well as the identifier, but nothing I've tried has returned .exists true for the accessoryView.
Am I trying to access the cell incorrectly? Or, is it actually not possible to do what I'm attempting?
The code for my test is:
XCUIDevice.sharedDevice().orientation = .Portrait
let app = XCUIApplication()
wait()
let tablesQuery = app.tables
tablesQuery.cells.elementBoundByIndex(0).tap()
wait()
tablesQuery.cells.elementBoundByIndex(1).tap()
What am I not understanding properly here? Any advice would be greatly appreciated.
(I know I could have used a standard UITableViewCell with the data entry done on the child view, but I prefer not to change the design of my app to accommodate XCTest's, seems a bit backwards.)

I have a sub-classed UITableViewCell which contains a textField that does not fill the entire cell...
I am simulating a tap on the second cell using
tablesQuery.cells.elementBoundByIndex(1).tap()
However, the simulator interprets it as a tap in the textField, so no segue occurs.
It sounds like your tap on the table view cell is being intercepted by the text field. When UI tests tap on a table view cell, the tap will be at the centre of the UI element's frame.
To offset the tap location from the centre of the cell, use coordinate(withNormalizedOffset:) and tap the coordinate instead of the element directly.
let cell = app.tables.cells.elementBoundByIndex(0)
// Retrieves coordinate that is 50% of the way along the cell
// and 20% of the way down the cell - adjust these values to
// find the right values to avoid tapping the text field area
// of the cell
let cellCoordinateForTap = cell.coordinateWithNormalizedOffset(CGVector(dx: 0.5, dy: 0.2))
cellCoordinateForTap.tap()

Related

I get wrong indexPath in the didSelectRowAt when the keyboard of the UITextView is dismissed by taping on the background

I have a tableView. The last row of which is the UITextView while the 2 cells above are clickable(Another viewController appears by tapping on them). When I begin editing the textfield a keyboard presents so the upper cells do not fit in anymore and we do not see them.
Then I decide to hide my keyboard by tapping on the background.
The problem is: when I tap on a certain point didSelectRowAt is called. This 'certain' point is any point which appears within the borders of the 2 clickable cells described above.
It seems like after dismissing the keyboard and restoring the initial UI a gesture of touching is recognized and the system thinks that the cell was selected.
Who had experienced this problem before? How can I cope with that bug? Please share your experience
This question is not clear. You get wrong index path selected or you don’t want any selection at all?
When you show keyboard and update UI, you can disable any selection in the table. After you’re done with the keyboard, you can enable it again.
https://developer.apple.com/documentation/uikit/uitableview/1614911-allowsselection

How can I get IndexPath of currently selected tableviewcell by voice over?

I'm using Voice Over in my application. I'm having hard time to figure out which table cell is currently selected when voice over is on. How can I know whenever user initiates single tap or navigate through any tableviewcell?
These are the things you can try:
use the UIAccessibilityFocusedElement global function
override accessibilityElementDidBecomeFocused and accessibilityElementDidLoseFocus on the cell
observe the UIAccessibilityElementFocused notification in NotificationCenter in situations where you need it (e.g. when the view controller for the table in question is showing)
Also what element will report focus will most probably depend on whether your UITableViewCell has isAccessibilityElement set to true or false.
While the above will probably help you with literally what you asked, it is also possible that your overall approach to accessibility in this situation might be wrong if you need the above information. If you share more info on the bigger picture / motivation what you are trying to achieve, it might turn out that the information about focused element might not be needed at all and that another solution is more proper.
If what you need is to add a hint for swiping, you can simply set accessibilityHint on the proper element (if you set isAccessibilityElement = true on the whole cell, then set that on the whole cell, otherwise try setting it on the label that VoiceOver reads in the cell), e.g. when you configure the cell for display (usually in tableView(_:cellForRowAt:)). In such case, you will not need to observe which element is focused, and simply let VoiceOver read hint available on that particular element/cell.

How to have DidSelectRow activate keyboard?

Goal
I want to have a keyboard (custom) to show when I click on a cell in my tableview and have said keyboard edit a label in the selected cell.
What I have read and tried
Stack overflow and other searched threads/tutorials
A Swift example of Custom Views for Data Input (custom in-app keyboard)
How to make custom keyboard only for my app in Swift?
iOS 8: Creating a Custom Keyboard in Swift
Along with other results and searches (also the recommended readings within these threads), these were great for me getting the keyboard the way I want it (which is app-specific, I don't want to have the user install the keyboard to use the app), however, none explain how I could "activate" the keyboard without a textfield.
My thought process is this: I will have a keyboard with a textfield in place in order to receive the input from the keys pressed. This input would then be sent to the label that is in the selected cell. The problem is in the keyboard showing without anything to call it...
Why I don't want a textfield in the cell: Because I think it is more smart/elegant to have the tableview cell activate the keyboard. I have seen this in other apps and I can't figure out how it is done.
Any help on this matter is much appreciated. I am completely new to programming, am using Swift (so have no clue Obj-C or the like).
Thank you!
Well after a lot of discussions around other websites, it is a shame to say it but what I wanted was actually impossible (like stated by Duncan). For some reason I thought that in programming that word did not exist, but alas it is there. Well, the way that I did work around this limitation was as replied here in the comments as well as from the resource materials I already read:
I have 2 views:
tableView - this will have the list of items that I would like to edit a value. Has multiple labels where one of them would be edited by the user.
keyboardView - custom keyboard that would allow user input.
For the keyboard I used the delegate method as described in "A Swift example of Custom Views for Data Input". This worked perfectly and would send the data over to the tableView under the keyWasTapped function.
Next was the tableView. I had 3 labels in the custom cell, where one was called valueLabel. I had to add a textField to my storyboard hidden behind the tableview with which the user will interact and in the didselectrow I included the command to summon the keyboard:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
textField.becomeFirstResponder()
}
From there I would grab the text from the textfield and update the UILabels in my custom cell. At least this way I can select a cell and not the textfield. So considering that the answer that would fit what I wanted is combination of the replies, I thought it would be best to say it here.
Thanks to Sandeep and Larme for their time.
TVDN,
Have a textField in cell not the label :) Create a custom cell create an IBOutlet to that class ffrom textField in cellForRowAtIndexPath
let tableCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as! myCell
tableCell.yourTextField.resignFirstResponder()
and in didSelectRowAtIndexPath
let tableCell = self.tableView.cellForRowAtIndexPath(indexPath)
self.tableView.dequeueReusableCellWithIdentifier("cell") as! myCell
tableCell.yourTextField.becomeFirstResponder()

Hiding objects within UITableViewCell iOS 8 (Swift)

I have a UITableViewCell that on touch, expands (dropdown). The user is then presented with a selection of options. When the user touches one of the options I want to briefly hide all the options, show an activity indicator spinning, display a confirmation message (on success) and then collapse the cell back to normal.
I'm having trouble hiding any object within the custom cell. The following simple code doesn't work (this is the correct superview corresponding to the cell):
var customCell: MyCustomCell = icon.superview.superview.superview as MyCustomCell
customCell.myLabel.hidden = false
I have tried hiding/showing a variety of different objects but nothing works. I've even popped it inside dispatch_async to ensure it runs on the main thread.
Additionally, Xcode 6 beta tells me that myLabel.hidden is read only. This also happens for other objects. Is this no longer the correct way to hide something?
I've had a search around but had no luck in finding an answer. If someone could help me out I'd be grateful! Thanks.
The usual way of doing something like this would be to implement the UITableViewDelegate method -tableView:didSelectRowAtIndexPath: to let you know when a row is tapped.
Then you can easily get and modify the cell
var customCell = self.tableView.cellForRowAtIndexPath(indexPath) as MyCustomCell
customCell.myLabel.hidden = false
I consider the line icon.superview.superview.superview to be a code smell. The multiple superview calls makes makes your code fragile and likely to break if you ever change the view hierarchy in your cell.

Adding a navigation accessory to a UITableCell

I am learning about TableViews in Xcode right now and I am having trouble finding some info on TableViewCell accessories.
My goal is to have a MasterTableView and a SubTableView. When a MasterTableCell is tapped to take the user to the SubTableView. But I'm stuck with something simple like showing a '>' on the right side of the cell to show that it has a SubTableView.
Do I need to design my own button? I thought there was a navigation image already available to me in the UI storyboard maker but it won't let me drag and use it in my custom cell I'm making.
Any thoughts or links to documentation would be great. I've looked in the developer library and all it tells me is that it is possible, not how to do it.
Thank you in advance.
If you are using a Prototype Cell in the Storyboard, just set the "Accessory" type in the Attributes inspector to "Disclosure Indicator".
If you create the cell programmatically, set
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
From the documentation:
UITableViewCellAccessoryDisclosureIndicator
The cell has an accessory
control shaped like a chevron. This control indicates that tapping the
cell triggers a push action. The control does not track touches.

Resources