Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xcode & Swift - Detecting user touch of UIView inside of UIScrollView

I am creating a game, similar to Flappy Bird but the user holds their finger on the screen and dodges the obstacles, rather than tapping to make the bird fly.

I am doing this by having a UIScrollView, in which UIView's are used as obstacles. When the user touches a UIView, the game is over.

How do I detect the users touch of a UIView from within a UIScrollView? I am using Swift with Xcode Beta 4.

EDIT: This is screenshot of the game

This is screenshot of the game

As you can see, the user moves their finger between the grey blocks (UIViews) as they scroll up.

like image 591
user2397282 Avatar asked Jul 31 '14 14:07

user2397282


People also ask

What is Apple Xcode used for?

Xcode provides developers a unified workflow for user interface design, coding, testing, and debugging. The Xcode IDE combined with the Swift programming language make developing apps easy and fun. To test or run applications on an iPhone, iPad, Apple TV, or Apple Watch all you need is a free Apple ID.

What is Xcode in Mac?

Xcode is a complete developer toolset for creating apps for Mac, iPhone, iPad, Apple Watch, and Apple TV. Xcode brings user interface design, coding, testing, debugging, and submitting to the App Store into a unified workflow.

Can Xcode run on Windows?

Given that Xcode works only on macOS, a solution to get Xcode on Windows would be to install macOS on a Windows PC by means of a virtualization app such as VMware or VirtualBox. Using a virtualization platform provides users with the full functionality of Xcode on your Windows machine.

Is Xcode only for Mac?

Xcode only runs on a mac.


2 Answers

By setting userInteractionEnabled to NO for your scroll view, the view controller will start receiving touch events since UIViewController is a subclass of UIResponder. You can override one or more of these methods in your view controller to respond to these touches:

  • touchesBegan: withEvent:
  • touchesMoved: withEvent:
  • touchesEnded: withEvent:
  • touchesCancelled: withEvent:

I created some example code to demonstrate how you could do this:

class ViewController: UIViewController {     @IBOutlet weak var scrollView: UIScrollView!      // This array keeps track of all obstacle views     var obstacleViews : [UIView] = []      override func viewDidLoad() {         super.viewDidLoad()          // Create an obstacle view and add it to the scroll view for testing purposes         let obstacleView = UIView(frame: CGRectMake(100,100,100,100))         obstacleView.backgroundColor = UIColor.redColor()         scrollView.addSubview(obstacleView)          // Add the obstacle view to the array         obstacleViews += obstacleView     }      override func touchesBegan(touches: NSSet!, withEvent event: UIEvent!) {         testTouches(touches)     }      override func touchesMoved(touches: NSSet!, withEvent event: UIEvent!) {         testTouches(touches)     }      func testTouches(touches: NSSet!) {         // Get the first touch and its location in this view controller's view coordinate system         let touch = touches.allObjects[0] as UITouch         let touchLocation = touch.locationInView(self.view)          for obstacleView in obstacleViews {             // Convert the location of the obstacle view to this view controller's view coordinate system             let obstacleViewFrame = self.view.convertRect(obstacleView.frame, fromView: obstacleView.superview)              // Check if the touch is inside the obstacle view             if CGRectContainsPoint(obstacleViewFrame, touchLocation) {                 println("Game over!")             }         }     }  } 
like image 156
s1m0n Avatar answered Oct 13 '22 20:10

s1m0n


You can programmatically add a gesture recognizer as follows

var touch = UITapGestureRecognizer(target:self, action:"action") scrollView.addGestureRecognizer(touch) 

However, this gesture recognizer won't work for you. UITapGestureRecognizer will only return for a tap, not a tap and hold, and UILongPressGestureRecognizer doesn't give information about location, so you want to use a UIPanGestureRecognizer. It continually tells you how far the touch has moved.

var touch = UIPanGestureRecognizer(target:self, action:"handlePan") scrollView.addGestureRecognizer(touch)  @IBAction func handlePan(recognizer:UIPanGestureRecognizer) {     let translation = recognizer.translationInView(self.view)     recognizer.setTranslation(CGPointZero, inView: self.view) } 

You can use the constant "translation" to move your object, it represents the distance the person has slid their finger. Use that plus the location of your bird to move the bird to a new point. You have to reset the translation to zero after this function is called.

Edit: With the format of your game, this code should be the best method.

So, all together, the code to find the location of your finger should be as follows.

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {     for touch: AnyObject in touches {         let location = touch.locationInView(yourScrollView)     } }   @IBAction func handlePan(recognizer:UIPanGestureRecognizer) {     let translation = recognizer.translationInView(self.view)     var currentLocation : CGPoint = CGPointMake(location.x+translation.x, location.y+translation.y)     recognizer.setTranslation(CGPointZero, inView: self.view) } 

currentLocation is a CGPoint containing the location of the current touch, wherever the finger is slid to. As I do not know how you are creating the views to be avoided, you will have to use the y coordinate of currentLocation to determine the x boundaries of the views that are to be avoided at that y, and use < or > comparators to determine if the x boundary of the touch is inside either of those views.

Note: you have to declare location so it can be accessed in handlePan

var location : CGPoint = CGPointZero 
like image 36
trumpeter201 Avatar answered Oct 13 '22 20:10

trumpeter201