Is it possible to simulate two finger swipe in iOS UI Testing? - ios

I want to perform a two finger swipe in my UI Test. I am using XCUITest framework. I tried all pinch and rotate methods but Seems like there is no built in support for this functoinality.

I don't know if it will work, but you can try to simulate two different fingers dragging screen simultaneously. Something like this:
XCUIApplication *app = [[XCUIApplication alloc] init];
[app launch];
// Set a coordinate near the left-edge, we have to use normalized coords
// so you set using percentages, 1% in on the left, 15% down from the top
XCUICoordinate *coord1 = [app coordinateWithNormalizedOffset:CGVectorMake(0.01, 0.15)];
// Then second coordinate 40 points to the right
XCUICoordinate *coord2 = [coord1 coordinateWithOffset:CGVectorMake(40, 0)];
// Third coordinate 100 points down from the first
XCUICoordinate *coord3 = [coord1 coordinateWithOffset:CGVectorMake(0, 100)];
// Last one is 100 points down from the second
XCUICoordinate *coord4 = [coord2 coordinateWithOffset:CGVectorMake(0, 100)];
// Perform a drag from coord1 to coord3
[coord1 pressForDuration:0.5f thenDragToCoordinate:coord3];
// Perform a drag from coord2 to coord4
[coord2 pressForDuration:0.5f thenDragToCoordinate:coord4];

Related

XCode7 UITests how to test screen edge pan gestures?

I have the following gesture recognizer in my app. I've looked at xCode7 UI and see that it has swipe up/down/left/right, but no pan or edge pan gestures.
How can one test or initiate screen edge pan gesture for UITesting purposes?
UIScreenEdgePanGestureRecognizer *leftEdgeGesture = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:#selector(show)];
leftEdgeGesture.edges = UIRectEdgeLeft;
leftEdgeGesture.delegate = self;
[self.view addGestureRecognizer:leftEdgeGesture];
I spent a while trying to figure this out, navigating around the element hierarchy. Lots and lots of googling and finding nothing.
I gave up twice, then figured it out.
We just need two coords on the main app screen, and drag one to the other.
Works a treat!
XCUIApplication *app = [[XCUIApplication alloc] init];
[app launch];
// Set a coordinate near the left-edge, we have to use normalized coords
// so you set using percentages, 1% in on the left, 15% down from the top
XCUICoordinate *coord1 = [app coordinateWithNormalizedOffset:CGVectorMake(0.01, 0.15)];
// Then second coordinate 40 points to the right
XCUICoordinate *coord2 = [coord1 coordinateWithOffset:CGVectorMake(40, 0)];
// Perform a drag from coord1 to coord2
// Simulating swipe in from left edge
[coord1 pressForDuration:0.5f thenDragToCoordinate:coord2];
Hopefully this will help everyone else who has been struggling to simulate an edge swipe.
Piggybacking on Chris' awesome answer, here's the swift version:
func pressCoordinate(x xCoordinate: Double, y yCoordinate: Double, app2call: XCUIApplication=XCUIApplication())
{
let normalized = app2call.coordinate(withNormalizedOffset: CGVector(dx: 0.01, dy: 0.5))
let coordinate = normalized.withOffset(CGVector(dx: xCoordinate, dy: yCoordinate))
normalized.press(forDuration: 0.5, thenDragTo: coordinate)
}

How to simulate simultaneous touch in iOS Simulator

I currently have two buttons on my screen , one on the left and one on the right , I wanted to know if there is a way in the iOS Simulator to simulate both buttons being pressed at the same time. I tried pressing ⌥ Alt on the simulator as a result two circles appear. I can position one circle to the first button on the left however I am not sure how to position the next circle on the right button.
Once you have the two circles (using the Alt key), move the circles together, then hold the shift key: this will allow you to move the two circles anywhere on the simulator screen.
Then let go the key and click.
I just tried it with this code:
-(void)tapTwo:(UITapGestureRecognizer*)recognizer
{
CGPoint p1 = [recognizer locationOfTouch:0 inView:self.view];
CGPoint p2 = [recognizer locationOfTouch:1 inView:self.view];
NSLog(#"Points: %# and %#",NSStringFromCGPoint(p1),NSStringFromCGPoint(p2));
}
- (void)viewDidLoad {
[super viewDidLoad];
UITapGestureRecognizer* r = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapTwo:)];
r.numberOfTouchesRequired = 2;
[self.view addGestureRecognizer:r];
}
and it worked as expected.
For the two Circles, all you need to do is click windows + alt button together and to move those two circles to desired position you need to press shift button and drag your cursor to that position.
(The solution is for windows keyboard)

Parenting views in Xcode

Currently i am trying to implement the following. While making a compass, i would like to draw arrows(circles) at set locations and rotate around my view to display on compass.
I can use storyboard to create Imageviews and the like and parent them with one another.
I am trying to now do this programming code, as that when a new location is received by program it can display the new point on compass.
I have already worked out code to rotate around
Ideally my flow of code should be as follows:
For i = 1 to 5;
Draw empty square view[i]
Draw Circle and position within square[i] at co-ordinate (x,y) (pretty much at the north point of compass)
Parent circle to Square
Rotate square[i] to x degrees.
Next i
My question is how do i programmatically draw these views and then how do i parent the views. Such that i can rotate one with the other at a fixed point.
Thanks.
this is not exact answer, but it may help you.just play with value of i(loop index)
-(void) rotateOn360Degree
{
int x,y;
double radious=30;
for(int i=1;i<=360;i++)
{
x = radious* cos((i * 3.14) / 180));
y = radious* sin((i * 3.14) / 180));
UIView *tmpView = [[UIView alloc] init];
[tmpView setBackgroundColor:[UIColor greenColor]];
[tmpView.layer setCornerRadius:5];
tmpView.frame = CGRectMake(x,y, 10, 10);
[self.view addSubview:tmpView];
}
}

PanGesture with repeatable background using SpriteKit

I'm having trouble getting a repeatable background to work in my game menu.
The user can slide a finger across the screen to select a character to play.
I have a parallax effect working with various backgrounds as the characters slide into view.
Sample below.
- (void)didMoveToView:(SKView *)view
{
self.pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:#selector(dragScene:)];
self.pan.minimumNumberOfTouches = 1;
self.pan.delegate = self;
[self.view addGestureRecognizer:self.pan];
}
- (void)dragScene:(UIPanGestureRecognizer *)gesture
{
CGPoint trans = [gesture translationInView:self.view];
SKAction *moveSky = [SKAction moveByX:trans.x*0.03 y:0 duration:0];
[_skyBackground runAction:moveSky];
}
I would like to repeat the backgrounds. I know how to do this with automatically scrolling backgrounds but I can't seem to get it to work here. It needs to repeat in both directions, left and right.
Thanks for any help!
You can create two more background nodes - one to the left of your current background node and one to the right. Move them aswell any time you move your existing _skyBackground node.
Then, in the update method, check if any of the three nodes needs to be "shifted" - either to behind the other two or in front. You're basically swapping the three nodes' positions if needed.
-(void)update:(NSTimeInterval)currentTime {
//get the left background node (or if using an ivar just use _leftNode)
SKSpriteNode *leftNode = (SKSpriteNode*)[self childNodeWithName:#"leftNode"];
//my positioning might be off but you'll get the idea
if (leftNode.position.x < -leftNode.size.width*2)
{
leftNode.position = CGPointMake(leftNode.size.width, leftNode.position.y);
}
if (leftNode.position.x > leftNode.size.width*2)
{
leftNode.position = CGPointMake(-leftNode.size.width, leftNode.position.y);
}
//repeat the same for _skyBackground and _rightNode
}
You may need more than 3 images if there's a slight gap between images as they're shifted.

New foursquare venue detail map

I really love the way foursquare designed venue detail view. Especially the map with venue location in the "header" of view ... How was it done? Details are obviously some uiscrollview (maybe uitableview?) and behind it (in the header) there is a map so when you scroll up the map is beeing uncovered as the scroll view bounces... does anyone has an idea how to do this?
Here's the way I manage to reproduce it:-
You need a UIViewController with a UIScrollView as its view. Then, the content of the UIView you add to your scrollview should look like this :-
- The frame of the MKMapView have a negative y position. In this case, we can only see 100pts of the maps in the default state (before dragging).
- You need to disable zooming and scrolling on your MKMapView instance.
Then, the trick is to move down the centerCoordinate of the MKMapView when you drag down, and adjust its center position.
For that, we compute how much 1point represent as a delta latitude so that we know how much the center coordinate of the map should be moved when being dragged of x points on the screen :-
- (void)viewDidLoad {
[super viewDidLoad];
UIScrollView* scrollView = (UIScrollView*)self.view;
[scrollView addSubview:contentView];
scrollView.contentSize = contentView.frame.size;
scrollView.delegate = self;
center = CLLocationCoordinate2DMake(43.6010, 7.0774);
mapView.region = MKCoordinateRegionMakeWithDistance(center, 1000, 1000);
mapView.centerCoordinate = center;
//We compute how much latitude represent 1point.
//so that we know how much the center coordinate of the map should be moved
//when being dragged.
CLLocationCoordinate2D referencePosition = [mapView convertPoint:CGPointMake(0, 0) toCoordinateFromView:mapView];
CLLocationCoordinate2D referencePosition2 = [mapView convertPoint:CGPointMake(0, 100) toCoordinateFromView:mapView];
deltaLatFor1px = (referencePosition2.latitude - referencePosition.latitude)/100;
}
Once those properties are initialized, we need to implement the behavior of the UIScrollViewDelegate. When we drag, we convert the move expressed in points to a latitude. And then, we move the center of the map using the half of this value.
- (void)scrollViewDidScroll:(UIScrollView *)theScrollView {
CGFloat y = theScrollView.contentOffset.y;
// did we drag ?
if (y<0) {
//we moved y pixels down, how much latitude is that ?
double deltaLat = y*deltaLatFor1px;
//Move the center coordinate accordingly
CLLocationCoordinate2D newCenter = CLLocationCoordinate2DMake(center.latitude-deltaLat/2, center.longitude);
mapView.centerCoordinate = newCenter;
}
}
You get the same behavior as the foursquare app (but better: in the foursquare app, the maps recenter tends to jump, here, changing the center is done smoothly).
The example above is nice. If you need more help, I think they're using something very similar to RBParallaxTableViewController. https://github.com/Rheeseyb/RBParallaxTableViewController
It's essentially the same effect that Path uses for its header photo.
Yonel's answer is nice, but I found a problem as I have a pin at the center of the map. Because the negative Y, the point is hidden under my UINavigationBar.
Then, I didn't set the Negative Y, and I correct my mapView.frame according the scroll offset.
My mapView is 320 x 160
_mapView.frame = CGRectMake(0, 160, 320, -160+y);
Hope this helps someone.

Resources