Found my TTPhotoView bug

TTPhotoView bug ExampleThis is a tip for anyone hacking TTPhotoViewController, and specifically TTPhotoView. If you’re finding swiping only rotating between three photos, and if there’s a mix of landscape and portrait then it gets a redraw bug that looks like this:

then you’ve probably disabled updateLayer (perhaps because it wasn’t working for photos with orientations other than Up) but didn’t replace it with [self setNeedsDisplay]. You’re welcome.
Also, for anyone else trying to untie TTPhotoView from TTURLCache and instead work with images you can’t load asynchronously: don’t. Instead make it work with fake URLs, force-feeding the cache as you go. Hey ALAssetLibrary, thanks for being async in all the wrong places.


A multitouch UIPanGestureRecognizer trick

Even though I wanted our app to still support iPhone OS 3.1, I realized that since our extra gesture-based features are iOS4 only, I could use UIGestureRecognizer for those. I already had a UIView subclass I was using as a transparent overlay where I implemented my custom tap detection and drag tracking. What I did was bite the bullet and replaced it completely with a plain UIView with gesture recognizers attached. In a few minutes I was able to duplicate all the behaviour that took lots of trial and error to get right. Kudos to everyone at Apple who worked on UIGestureRecognizer.

One part of the new behaviour I wanted to try out was a drag that started with two fingers. It looked like UIPanGestureRecognizer was working but it was ending the gesture when one finger was lifted. I wanted to support starting with a two-finger tap but then still track if the user lifts one finger.

I thought I’d have to implement a custom recognizer subclass when I came upon a little hack that seems to work: In my action method, I change the minimumNumberOfTouches property from 2 to 1 on the fly when called in the Began state, then set it back to 2 when called with Ended or Cancelled.

- (void)drag2Fingers:(UIPanGestureRecognizer *)sender {
    if (sender.state == UIGestureRecognizerStateBegan) {
        sender.minimumNumberOfTouches = 1;
    } else if (sender.state == UIGestureRecognizerStateEnded ||
               sender.state == UIGestureRecognizerStateCancelled) {
        sender.minimumNumberOfTouches = 2;

This seems to work but maybe it’s presumptuous to think it’s always going to. I think I’ll be doing that custom recognizer subclass in a future update.