これが発生し始めた理由は、のプロパティUIView
の値であるインスタンスが、そのビューのサイズをそのスーパービューのサイズに変更するようにメッセージを受け取ることがあるからです。UIViewController
view
特に、ドキュメント化されていないメソッドviewDidMoveToWindow:shouldAppearOrDisappear:
は、ビュー コントローラーview
がウィンドウに追加されたときに呼び出されます。この例では、アプリケーションの起動時に発生しています。このとき、ビュー コントローラのview
インスタンスがメイン ウィンドウのサイズ以上の場合、そのスーパービューのサイズにサイズ変更されます。
元のコードは、.xibs から読み込まれた 2 つのビューを取得し、ウィンドウのサイズである 768 * 1024 にサイズを変更しました。これは、ウィンドウで が呼び出される前に発生し、最終的にサイズ変更がトリガーされます。 -makeKeyAndVisible
アプリのデリゲートで KVO を使用して、フレームのサイズが変更されるのを確認しました。サイズ変更時のスタック トレースは次のとおりです。
* thread #1: tid = 0x1f03, 0x000030f9 scroller`-[ViewController observeValueForKeyPath:ofObject:change:context:] + 105 at ViewController.m:71, stop reason = breakpoint 1.1
frame #0: 0x000030f9 scroller`-[ViewController observeValueForKeyPath:ofObject:change:context:] + 105 at ViewController.m:71
frame #1: 0x0093ad91 Foundation`NSKeyValueNotifyObserver + 345
frame #2: 0x0093a895 Foundation`NSKeyValueDidChange + 438
frame #3: 0x0092033e Foundation`-[NSObject(NSKeyValueObserverNotification) didChangeValueForKey:] + 131
frame #4: 0x009cdcb4 Foundation`_NSSetRectValueAndNotify + 187
frame #5: 0x000e1786 UIKit`-[UIViewController viewDidMoveToWindow:shouldAppearOrDisappear:] + 657
frame #6: 0x0005310c UIKit`-[UIView(Internal) _didMoveFromWindow:toWindow:] + 1040
frame #7: 0x00052edb UIKit`-[UIView(Internal) _didMoveFromWindow:toWindow:] + 479
frame #8: 0x0005d5ab UIKit`-[UIScrollView _didMoveFromWindow:toWindow:] + 65
frame #9: 0x00052edb UIKit`-[UIView(Internal) _didMoveFromWindow:toWindow:] + 479
frame #10: 0x0004f692 UIKit`-[UIView(Hierarchy) _postMovedFromSuperview:] + 158
frame #11: 0x0005446f UIKit`-[UIView(Internal) _addSubview:positioned:relativeTo:] + 1633
frame #12: 0x0004e14b UIKit`-[UIView(Hierarchy) addSubview:] + 56
frame #13: 0x0003d550 UIKit`-[UIWindow addRootViewControllerViewIfPossible] + 380
frame #14: 0x0003d670 UIKit`-[UIWindow _setHidden:forced:] + 280
frame #15: 0x0003d836 UIKit`-[UIWindow _orderFrontWithoutMakingKey] + 49
frame #16: 0x0004472a UIKit`-[UIWindow makeKeyAndVisible] + 35
frame #17: 0x00002575 scroller`-[AppDelegate application:didFinishLaunchingWithOptions:] + 661 at AppDelegate.m:21
frame #18: 0x00015386 UIKit`-[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1292
frame #19: 0x00016274 UIKit`-[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 524
frame #20: 0x00025183 UIKit`-[UIApplication handleEvent:withNewEvent:] + 1027
frame #21: 0x00025c38 UIKit`-[UIApplication sendEvent:] + 68
frame #22: 0x00019634 UIKit`_UIApplicationHandleEvent + 8196
frame #23: 0x0139eef5 GraphicsServices`PurpleEventCallback + 1274
frame #24: 0x01488195 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 53
frame #25: 0x013ecff2 CoreFoundation`__CFRunLoopDoSource1 + 146
frame #26: 0x013eb8da CoreFoundation`__CFRunLoopRun + 2218
frame #27: 0x013ead84 CoreFoundation`CFRunLoopRunSpecific + 212
frame #28: 0x013eac9b CoreFoundation`CFRunLoopRunInMode + 123
frame #29: 0x00015c65 UIKit`-[UIApplication _run] + 576
frame #30: 0x00017626 UIKit`UIApplicationMain + 1163
frame #31: 0x000022ad scroller`main + 141 at main.m:16
UIViewController
ビューをインスタンス化し、同時にそれをスクロール ビューに追加することにより、コンテンツ ビューが のビュー インスタンスであるため、これが発生することを確認できます。ViewController
のviewDidLoad
実装の最後に次のコードを追加しました。
CGRect frame3 = frame2;
frame3.origin.x = 768.0f * 2.0f;
UIView *thirdView = [[UIView alloc] initWithFrame:frame3];
[thirdView setBackgroundColor:[UIColor redColor]];
[self.scrollView addSubview:thirdView];
コンテンツ サイズを割り当てる行を次のように変更するだけでなく、
[self scrollView].contentSize = CGSizeMake(768 * 3, 1024);
このビューはフレーム セットを取得せずmakeKeyAndVisible
、正しい位置にあります。
この問題を回避するには、ウィンドウが-makeKeyAndVisible
呼び出された後にビュー階層を設定することをお勧めします。おそらく、viewWillAppear で (同じ問題が発生するかどうかは不明です)、またはコードを構造化してスクロールのレイアウトを遅らせることをお勧めします。見る。または、このバグを明示的に元に戻すために、後でフレームを再設定します。
これが何が起こっていたのかを説明するのに役立ち、私が提供する証拠が明確で信頼できるものであることを願っています。特定のケースの修正が既に行われているようですが、うまくいけば、この回答は、UIViewController
スクロールビュー内にビューが配置されている場合のフレームの誤動作に対する一般的な解決策となります。