Attempts to tap a UIButton in a UITableViewCell using UI Automation fail with "could not be tapped" - iphone

I have an iPhone app that I'm testing using UI Automation.
I have a button in a UITableViewCell but when I try to tap on it using UI Automation I get the following error.
Script threw an uncaught JavaScript error: target.frontMostApp().mainWindow().scrollViews()[0].elements()[element_name].tableViews()[0].elements().firstWithPredicate(name contains[c] 'Brooklyn').elements()["detailsButton"] could not be tapped
I have enabled accessibility on the button in Interface Builder and assigned the accessibility label (and identifier) "detailsButton". I can retrieve the button element and have verified that it is valid. I just can't tap it for some reason.
The UIButton is a round rectangular button with user interaction enabled. Thanks for any feedback.

You can alloc the UIButton except using round rect button. And also you can set target action of button in your controller class where table view delegate methods are presents.

Try asserting first if the button exists, use tuneup_js for easy assertions.
Then assert if the button is enabled.
Have you tried:
target.frontMostApp().mainWindow().scrollViews()[0].elements()[element_name].tableViews()[0].**cells()**.firstWithPredicate("name contains[c] 'Brooklyn'").elements()["detailsButton"]?
Also post another picture which shows the UIATableCell expanded where the detailsButton exists.

You have to use ButtonType=Custom

I don't know why you are using UI Automation. But as much I know about adding UIButton in a tableviewcell-
1) just add UIButton in UITableViewCell.
2) set UIButton's tag value and add target to that button.
3) In the target button method, you can get the UIButton object and do your stuff over there..
Hope this helps you out.

but=[UIButton buttonWithType:UIButtonTypeCustom];
You must use a custom button type.

I have met the same problem. After I added the delay it works.
UIATarget.localTarget().delay(1);

You can dispatch a tap event over the entire window:
function tap_from_window(elem) {
var mainWindow = target.frontMostApp().mainWindow();
var elemRect = elem.rect();
var windowRect = mainWindow.rect();
var xPos = (20 + elemRect.origin.x) / windowRect.size.width;
var yPos = (50 + elemRect.origin.y) / windowRect.size.height;
mainWindow.tapWithOptions({tapOffset:{x:xPos, y:yPos}});
}
var target = UIATarget.localTarget();
var window = target.frontMostApp().mainWindow();
var tableView = window.scrollViews()[0].elements()[element_name].tableViews()[0];
tap_from_window(tableView.elements().firstWithPredicate(name contains[c] 'Brooklyn'))
Like many things related to iOS, I have no idea why the element cannot be tapped directly. I adapted the above function from the code in this post: scrollToVisible error while testing on a device, UIAutomation

Related

iOS Determine button that was programmatically created

I have made a horizontal scroll view with images and buttons in it using a for loop, what i want to do now is when a button is pressed, open the image it corresponds to full screen. The issue im having is determining which button has been pushed. I am using :
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
then :
-(void)buttonPressed:(UIButton *)sender {}
What can i do to fix this? Thanks
Which button has been pushed
Create a property to store a tag. In the buttonPressed method set the property to sender.tag
Now you can know which was the button who got pressed last.
The sender is the button that the user has tapped, so when you create the buttons you could use the tag property and set it to an index of an array where you hold your images. But this could be a bit unstable if you change the order or amount of images or buttons for example so be prepared to check for that.
one way to do so is to keep references of your button (with a property, an attribute in your class) and test if it is the good one in your buttonPressed method
- (void)buttonPressed:(UIButton *)sender {
if (sender == self.myButton) {
// DO YOUR WORK HERE
}
}
you can also create a method for this and only this one button
by the way it is better to say
- (IBAction)buttonPressed:(UIButton *)sender
you then can set the target of your button in the interface builder interface
set tag for each button in the for loop but.tag=i;
-(void)buttonPressed:(UIButton *)sender {
if (sender.tag==1){
//display image 1
}
else if ....
}

Replace or extend UIBarButtonItem selector

I'm trying to make a custom UIToolbar which handles rotation and custom arrangement. When it's in portrait mode some of the barbuttonitems will not be visible, so I add a "more" button from which pops up a little view with these items. My problem is that when my current orientation is portrait and when I select a visible barbuttonitem ( which is not in popup ) I want to close the popup if it's open. I want the smae behavior for the uibarbuttons in the popupview to close the popup after tap.
So I'm trying to replace somehow the UIBarButtonItem's selector with my own, in which I call the already defined actions, like this :
-(SEL)extendOriginal:(UIBarButtonItem *) uibb
{
if (popup) popup.hidden = YES;
[uibb.target performSelector:uibb.action];
// return ?? do what ??
}
But how do I replace the original selector to call this custom method with my custom UIToolbar as its target ? Or how could I "extend" the original selector with this call ? Sorry if question is lame :)
Edit: In other words, I want 2 actions with 2 separate targets to be executed when UIBarButtonItem is tapped.
Thanks!
This -(SEL)extendOriginal:(UIBarButtonItem *) uibb doesn't make any sense.
I assume your are setting the target and the action of the bar button item somewhere. There you can set any method with one argument id or UIBarButtonItem* as the selector.
Therefore try to change your code to
- (void)myMethod:(UIBarButtonItem *) uibb
{
if (popup) popup.hidden = YES;
// do cool stuff here
}
and set the target as
[[UIBarButtonItem alloc] initWithTitle: #"Blabla" style: UIBarButtonItemStylePlain target: self action: #selector(myMethod:)];
Finally, I found a way to do it, not the prettiest, but it works.
In the custom toolbar class I created in its layout method a UITapGestureRecognizer to handle taps. I've set the cancelsTouchesInView to false and in the
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
method I'm returning true only for my toolbar's subviews.
This way the original target and action of each UIBarButtonItem remains the same and the supplementary code to handle my popup is the action of the UIGestureRecognizer.
Another problem was to distinguish between the tapped items on the toolbar (the tapped view in touch.view is some undocumented view, yay), eventually I did it with some BOOL iVars.
I hope this will help somebody with the same problem.

MonoTouch : Can I use a UILabel to show a phone number?

I need to show a phone number in a view and that when clicked a call is initiated. Currently I'm using an UILabel and I have no idea how to do it.
Is this the correct control? If no which one would be?
If it's the correct one, how can I do it?
An UILabel could be used (kind of showing a link) but an UIButton might be more appropriate.
You can find the code to initiate the code from this question (and answer).
Using a UIButton and the code from above would give you:
var btn = UIButton.FromType(UIButtonType.RoundedRect);
btn.Frame = new RectangleF (10,10,100,200);
btn.SetTitle ("call me", UIControlState.Normal);
btn.TouchUpInside += delegate {
UIApplication.SharedApplication.OpenUrl (NSUrl.FromString ("tel://411"));
};

iPhone iOS 4 UIButton toggle highlighted state on and off

I got a UIButton with style "Info Dark" set up in interface builder in my iPhone 4 app. One of the properties of the button is "Highlighted", which displays a white highlight around the button.
I would like to toggle this white highlight on and off, indicating if the button function is active or not.
The button is linked for "Touch up inside" event in the interface builder with this callback:
infoButton.highlighted = !infoButton.highlighted;
After the first touch, the highlight disappears and does not toggle as I expect it to. What else do I need to do to make the highlight toggle and display the state of the button?
Thank you!
Update:
When loaded from the interface builder, the button stays highlighted, even as the view appears/disappears. What causes this to happen is the "shows touch on highlight" interface builder property. If I assign the code above to another button, the info button highlights on and off as expected. However, the touches of the info button itself interfere with the above code, causing the button to lose the "touch" highlight
Update 2: I added another info button, directly below the first info button, in the interface builder and made it glow permanently. To create the appearance of the toggle, I hide and unhide the glowInfoButton below the real one. This works as expected:
infoButton.highlighted = NO;
glowInfoButton.highlighted = YES;
glowInfoButton.enabled = NO;
glowInfoButton.hidden = YES;
- (IBAction)toggleInfoMode:(id)sender {
// infoButton.selected = !infoButton.selected;
glowInfoButton.hidden = !glowInfoButton.hidden;
}
The Highlighted image is what displays when the UIButton is being pressed, and is controlled within the UIButton itself.
You're looking for the Selected property. You can set a Selected Image in IB, and then put a infoButton.selected = !infoButton.isSelected; in your TouchUpInside callback.
The highlighted property doesn't work like that, buttons aren't toggles.
It's just to know if the button is being pressed, if I'm correct.
If you want to implement that functionality, I recommend you subclass UIButton or UIControl.
Now that I see what you really were after I would advise subclass UIButton and check for a call to an event then toggle highlight state accordingly. You can do this without adding the dummy button.
in a custom button class implementation file place the following code, or similar:
#import "HighlightedButton.h"
#implementation HighlightedButton
BOOL currentHighlightState;
-(void)toggleHighlight:(id)sender {
self.highlighted = currentHighlightState;
}
-(void)sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {
//get the string indicating the action called
NSString *actionString = NSStringFromSelector(action);
//get the string for the action that you want to check for
NSString *touchUpInsideMethodName = [[self actionsForTarget:target forControlEvent:UIControlEventTouchUpInside] lastObject];
if ([touchUpInsideMethodName isEqualToString:actionString]){
//toggle variable
currentHighlightState = !currentHighlightState;
//allow the call to pass through
[super sendAction:action to:target forEvent:event];
//toggle the property after a delay (to make sure the event has processed)
[self performSelector:#selector(toggleHighlight:) withObject:nil afterDelay:.2];
} else {
//not an event we are interested in, allow it pass through with no additional action
[super sendAction:action to:target forEvent:event];
}
}
#end
That was a quick run at a proper solution, there is a flicker on toggle that you may not like. I am sure if you play around with some changes that can be corrected. I tried it and actually like it for your stated case.
The highlighted state of a UIButton is simply setting the button's alpha to 0.5f. So if you set the button to not change on highlight, then just toggle the alpha between 0.1 and 0.5.
For example:
- (void)buttonPressed:(id)sender {
if((((UIButton*)sender).alpha) != 1.0f){
[((UIButton*)sender) setAlpha:1.0f];
} else {
[((UIButton*)sender) setAlpha:0.5f];
}
}
Perhaps what you really want is
infoButton.enabled = NO;
This will dim the button and disable touches when set to no, allow normal operation when set to YES.
or in your case:
infoButton.enabled = !infoButton.isEnabled;
to toggle the availability of same.
If you put this in your touchupinside event, of course it will work only the first time. After that is disabled and does not receive touch events. You would put it in another method that decides whether or not the button should be enabled.
If you truly want it to change each time it is pressed then you probably should use a switch or you may look at the -imageForState, -setTitle:forState and/or -setTitleColor:forState methods. If you want to toggle the appearance each time it is touched, you could change these.

Access switch and textfield in tableview from another method

I'm having a tableview with a couple of cells with 4 uiswitches and one textfield inside. Simple question. I need a way to read all the positions of the switches and the string inside the textview by clicking a button. Tableview, textfield, switches and button is working fine. Just need to access the values of the switches and textfield from another method. By tagging the switches or something.
So how can I access the values from another method. Something like in tableview method:
...
UISwitch *switchView = [[option1 alloc] initWithFrame:CGRectZero];
switchView.tag = 3000;
cell.accessoryView = switchView;
...
And something like this in the button method:
...
BOOL status = [self.view viewWithTag:3000].on; //*Not a working method*
You are in the same class, nop ?
So maybe you could put your switch & co as class variable (declared in the header file). It would be easier ^^