iOS Recipes - Matt Drance [44]
}
Finally, we send every shadow to the back in the ‑repositionShadow: method. We do this because as table cells are reused, their z-order varies. Pushing the shadows to the back ensures there won’t be any strange cases where the shadow shows above normal table content. We additionally safeguard against the shadows clobbering table content by hiding them altogether based on the scroll position. Note that this code also accounts for the optional backgroundView property introduced in iOS 4.0.
ShadowedTables/Classes/PRPShadowedTableView.m
- (void)repositionShadow:(UIImageView *)shadowView {
if (self.backgroundView) {
[self insertSubview:shadowView aboveSubview:self.backgroundView];
} else {
[self insertSubview:shadowView atIndex:0];
}
}
This self-contained class is ready for reuse from any view controller or codebase. You can set background colors, headers, and footers and still get all four shadows for free. As you’ve now seen in two examples, the ‑layoutSubviews method can help manage the situation with a small amount of code.
Recipe 21 Place Static Content in a Zoomable Scroll View
Problem
You want to create a zoomable scroll view with points that do not zoom with the main content, like the pins in the Maps app. This is not as straightforward as it sounds: depending on where you place your “pins,” they either zoom with the content or move across the screen as the zoom scale changes.
Solution
UIScrollView makes it fairly easy to support arbitrary scrolling and zooming of content in your apps. This is all you have to do:
Set the minimum and maximum zoom scales to different values.
Set a delegate that specifies a content view for zooming.
Although simple, those steps are worth mentioning because they’re often forgotten. Forgetting either one of them disables zooming for that scroll view. But that’s not why we’re here. We’re here because we want to create static “pins,” on our scroll view, just like Maps and MKMapView do. Figure 26, Nonzooming scroll view content shows an example of this effect.
This recipe keeps select subviews in the same place and, at the same size, whenever the containing scroll view is zoomed.
Figure 26. Nonzooming scroll view content
* * *
Sounds simple, right? Not exactly. Let’s take a look at our options, illustrated in the ScrollViewPins project. The ScrollViewPinsViewController includes a scroll view, for which it serves as the delegate. It returns an instance of PRPGridView—a simple class that draws a grid using UIBezierPath—as the view for zooming. This is all we need to enable zooming in our scroll view.
ScrollViewPins/Classes/Demo View Controllers/ScrollViewPinsViewController.m
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return self.gridView;
}
All of the relevant connections between the views and view controller, as well as the required minimumZoomScale and maximumZoomScale values, are configured in ScrollViewPinsViewController.xib.
Now let’s add some subviews. The project presents three tabs, each with a different subclass of ScrollViewPinsViewController that exhibits slightly different behavior. Each view controller adds the same generated “pin view” to the screen but in significantly different ways. Run the project and take a look at how each tab differs, using two fingers (or drag in the Simulator with the option key held down) to zoom in and out.
The first tab adds the pin as a subview of the scroll view, independent of the grid we’re zooming. This sounds intuitive because, as stated before, we want the pin to keep its dimensions as the grid content scales. Select the Moving Pins tab to see for yourself. Unfortunately, there’s a wrinkle: the pin’s size doesn’t change as we zoom (good), but it does fly off the screen (bad). This “movement” occurs because the pin sits in the scroll view’s coordinate space, which changes as zooming occurs.
Let’s move on to the second tab, which adds the pin as a subview of the grid view—the view we’re zooming within the scroll view. Select the Zooming Pins tab to see this