ちなみに

scrollview.bounces = NO;

 とすることで、ドラッグで範囲外までスクロールしてから戻るという動作(スクロールバウンスアニメーション)を禁止できます。こいつはデフォルトはYESです。
 同じように

scrollview.bouncesZoom = YES;

 で、ピンチで許可したズーム範囲外までズームを許してから範囲内に戻る(ズームバウンスアニメーション)という動作をゆるします。こっちは逆にデフォルトがNOみたいっす。
 ズーム範囲を0.5~2.0(元々の0.1~10.0はいっぱいピンチしないと範囲外にいかないからね)あたりにして試してみてちょ。

 で、触ってて気づいたのが、ズームアウト、こんな感じのところで手を離すとスクロールができなくなるんですわ、前回のサンプル。

テン・シー・シー-1
右がはみ出てるのにスクロールできない。

 なにこれ?
 バグじゃんと思ったら、そのとおりでサンプルソースに、その対処法が書かれてました。それがこのデリゲートメソッドの処理でした。

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView
withView:(UIView *)view atScale:(float)scale {
[scrollView setZoomScale:scale+0.01 animated:NO];
[scrollView setZoomScale:scale animated:NO];
}

 なにこの意味不明の処理?と思ってたらバグ対策だったのねん。
 注釈にzoomToRect:animated:メソッドの不具合対策て書かれてました。3.0の後のバージョンでは治るよとのこと。
 もしかして3.0.1では治ってるかも。ま、シミュレータが3.0.1にならないと意味ないけど。

 このメソッドは、ズーミング(上のズームバウンスアニメーションも含め)が完了した時に呼ばれるみたいです。センタリングとか、ズームング後の、こまごました調整をするにはここかな。

[scrollView setZoomScale:1.0 animated:YES];

 とかを加えると、なにやっても(縮小しても、拡大しても)等倍表示の状態に戻されるようにできる。

 ユーザーの適当なズーミングで設定された倍率を、0.5、1.0、2.0とかいうふうにきっちりとした区切りに調整したりしたければ、ここらへんでやるとよさげ。ヘッダーで

double lastScale;

 を用意しておいて

if (scale > lastScale) {
scale = lastScale * 2.0;
} else if (scale < lastScale) {
scale = lastScale / 2.0;
}
lastScale = scale;
[scrollView setZoomScale:scale animated:YES];

 こんな感じ。汎用性ゼロですがサンプルということで。
 lastScaleはもちろん一番最初に1.0に初期化しておきます。

lastScale = 1.0;

 UIScrollViewの初期scale値は1.0なので、これだけでOKだけど、2.0から始めたいなら

lastScale = 2.0;
scrollview.zoomScale = lastScale;

 ですな。

 あと、せっかくなんでtestviewのフレームをずらして配置するとどうなるか試してみましたん。以下はlastScale = 1.0の等倍スケールスタートでテスト。

testview = [[testView alloc]
initWithFrame:CGRectMake(-300, -300, 500, 500)];

 初期表示はこんな感じ。

テン・シー・シー-2
たしかにframeの原点=(-300, -300)で指定してるから、これで正解ですな。

 ただし、左上方向にはスクロールできません。それと右下が見えてるにもかかわらず、右下方向にスクロールできる。
 これは、例えば横方向だと

500(内容部横ピクセル数) - 320(画面の横ピクセル数) = 180

 ということで、180ピクセルだけスクロールできると計算されるみたい。

テン・シー・シー-3

 実際はすでに300ピクセル左にめり込んだ状態なので、スクロールしなくても全面見えているが、上記計算のために180ピクセル動くので、残り20ピクセルが残された状態までスクロールできるわけですわ。

テン・シー・シー-4

 で、ズームインアウトして1/2にしてみると

テン・シー・シー-5
げえええ、消えたああああ。スクロールもできね~

 となる。
 縮小で、画像幅は

500 → 250

 となったから画面内におさまると判断してスクロールできないみたいっす。
 それと、一度ズーミングした後はtestViewの矩形の(0、0)以降の領域でスクロール範囲が再計算されるみたいで、ズームアウトして以下の状態に戻っても、今度はスクロールできなくなった。

テン・シー・シー-2

 testViewは、frameのoriginである(-300, -300)もスケーリングされて(-150, -150)になるかな~と想像してたんだけど、まったくスケーリングされないみたい。
 なので幅が250になったtestViewは全面的に画面外になると...

テン・シー・シー-6

 となり、画面外にいっちゃうわけです。
 確認のために

testview = [[testView alloc]
initWithFrame:CGRectMake(300, 300, 500, 500)];

として表示させると

テン・シー・シー-7

  となって、ここでピンチオープンクローズでズームアウトすると

テン・シー・シー-8
升目が増えてて1/2になっているのがわかるかな?

 というふうに、(300、300)のオフセットはそのまま画像だけ1/2になる。
 で、今回は

(300 + 250) - 320 = 230

 がスクロールできる範囲となるので、スクロールして全面表示できるぞっと。

 ま、frameのoriginの設定は慎重にってことですな。
 一緒にスクロールさせたいけど、ズームはさせたくないボタンビューを配置するとかに使うくらいかな~。それと、縮小表示時にUIScrollViewより小さくなったとき、埋め込まれたUIViewをセンタリングしたい時とか。

UIButton* button = [UIButton buttonWithType:UIButtonTypeInfoLight];
button.frame = CGRectMake(10, 10, 20, 20);
[scrollview addSubview:button];

 とすると
テン・シー・シー-10
こんな感じで「?」ボタンが出ます。スクロールに連動。

 ちなみにズームにまで連動させたければ

[testview addSubview:button];

 てやればいい。
 追記)

[self.view addSubview:button];

 とやれば、フローティング状態で常時左上に表示されるボタンにもなる。

 ここらへん、みごとに親側UIView(この場合UIScrollView)のCTMが、子側UIView(この場合testView)に影響を及ぼしてるみたいです。CTMについては「iPhoneアプリ開発、その(64)」~「iPhoneアプリ開発、その(69)」あたりを参照。
 これがtestViewを書き直してないのに、ズームされた画像が表示される理由でもある。

 scrollViewDidEndZoomingメソッドに0.5倍の時はセンタリングするようにtestview.frameを調整して今回はおしまい。サンプルをたたき台に、いろいろ試してみてください。
 次回こそタップ、ダブルタップ対応。

------------
サンプルプロジェクト:sc2.zip