Adding support for touch events

Currently, RestaurantDetailViewController has an outlet, ratingView connected to a ratings view object in the Restaurant Detail screen. It displays a rating of 3.5 stars, but you can't change the rating. To make ratings view respond when touched so that the user can change the rating, you will need to support touch events.

Perform the following steps:

  1. Click RatingsView.swift in the Project navigator and add the following code after the draw(_:) method:
override var canBecomeFirstResponder: Bool{
return shouldBecomeFirstResponder
}

canBecomeFirstResponder is a UIControl property that determines whether an object can become the first responder. Ratings view needs to become first responder to respond to touch events. This method returns false by default, so you need to override this method and return true in order for ratings view to be able to become first responder.

  1. Add the following code immediately after the canBecomeFirstResponder variable you just added:
override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
if self.isEnabled {
super.beginTracking(touch, with: event)
if (shouldBecomeFirstResponder && self.isFirstResponder) {
becomeFirstResponder()
}
handle(with:touch)
return true
} else {
return false
}
}

This method is called when the user touches any part of the ratings view on the screen. This is known as a touch event. First, it checks to see if the isEnabled property is true. If it is, the superclass implementation is called. After that, the ratings view on the screen is set to be the first responder, so it will capture touch events when it is touched and the handle(with:) method will be executed for every touch event.

  1. You'll see an error because you haven't implemented handle(with:) yet, so type the following code into the private extension:
func handle(with touch: UITouch){
let cellWidth = self.bounds.size.width / CGFloat(totalStars)
let location = touch.location(in: self)
var value = location.x / cellWidth

if (value + 0.5 < CGFloat(ceilf(Float(value)))) {
value = floor(value) + 0.5
} else {
value = CGFloat(ceilf(Float(value)))
}
updateRating(with: value)
}

func updateRating(with value:CGFloat) {
if (self.rating != value && value >= 0 &&
value <= CGFloat(totalStars)) {
self.rating = value
setNeedsDisplay()
}
}

handle(with:) takes a touch event as a parameter. First, cellWidth is assigned the ratings view's width, divided by 5. Next, the touch event's location within the ratings view is assigned to location. Then, value is assigned the x position of location, divided by cellWidth. The if statement calculates the rating corresponding to the position of the touch and calls updateRating(with:), passing it the value.

For example, let's say the ratings view's width is 200. cellWidth would be set to 200/5 = 40. Let's assume the user touched the screen at position x = 130; y = 17. value would be assigned 130/40 = 3.25. So, the if statement would evaluate (3.25 + 0.5 < ceilf(3.25)), which becomes (3.75 < 4.0), which returns true, thus value would be set to floor(3.25) + 0.5, which becomes 3.0 + 0.5, which is 3.5. So, updateRating(with:) would be passed a value of 3.5.

updateRating(with:) checks to see if value is not equal to the current rating and between 0 and 5. If it is, value is assigned to rating, and the screen is redrawn.

Following on from the preceding example, since 3.5 is between 0 and 5, it will be assigned to rating if it's not equal to the current value of rating.

You've added all the code that's necessary for the ratings view to respond to touches. Now, you'll need to update RestaurantDetailViewController to set the isEnabled property for the ratings view, as follows:

  1. Click RestaurantDetailViewController.swift in the Project navigator and modify the createRating() method, as follows:
func createRating() {
ratingView.rating = 3.5
ratingView.isEnabled = true
}

Setting the isEnabled property to true allows the ratings view to become the first responder and begin tracking touches, which will trigger handle(with:), which in turn calls updateRating(with:).

  1. Build and run your project. Tapping on the ratings view now changes the rating, depending on where you tapped. Tap between the first and second stars, as follows:

  1. The rating will change to 1.5. Now, let's take a look at the Review Form screen. The segue between the Add Review button and the Review Form screen has already been made for you. Tap the Add Review button, as shown in the following screenshot:

  1. The Review Form screen is displayed, as shown in the following screenshot (note that it should have a ratings view in the top cell, which you will add later):

Once the Review Form screen appears on the screen, you can't dismiss it, as the button actions for the Save and Cancel buttons have not been configured. In the next section, you'll configure the Cancel button so that it returns the user to the previous screen when tapped.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.21.162.87