回答:
Uliが以下にコメントしたように、それを行う適切な方法はlayoutSubviews
、そこにimageViewsをオーバーライドしてレイアウトすることです。
何らかの理由で、をサブクラス化してオーバーライドできない場合は、たとえダーティであってもlayoutSubviews
、監視bounds
は機能するはずです。さらに悪いことに、監視にはリスクがあります-Appleは、KVOがUIKitクラスで動作することを保証していません。ここでAppleエンジニアとの議論を読んでください:関連するオブジェクトはいつリリースされますか?
元の答え:
キーと値の監視を使用できます。
[yourView addObserver:self forKeyPath:@"bounds" options:0 context:nil];
そして実装:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (object == yourView && [keyPath isEqualToString:@"bounds"]) {
// do your stuff, or better schedule to run later using performSelector:withObject:afterDuration:
}
}
viewWillTransition
などを使用する必要があります
layoutSubviews
ビューの現在のサイズに応じて、異なるサブビューを追加/削除する必要があり、異なる制約を追加/削除する必要がある場合でも、推奨される方法を使用していますか?
ではUIView
、サブクラス、プロパティのオブザーバーは使用することができます。
override var bounds: CGRect {
didSet {
// ...
}
}
サブクラス化を行わない場合、スマートキーパスを使用したキーと値の監視は次のようになります。
var boundsObservation: NSKeyValueObservation?
func beginObservingBounds() {
boundsObservation = observe(\.bounds) { capturedSelf, _ in
// ...
}
}
frame
派生して実行時に計算されるプロパティです。あなたがそうする非常に賢明で知っている理由がない限り、これを上書きしないでください。それ以外の場合:bounds
または(さらに良い)を使用しますlayoutSubviews
。
override var bounds: CGRect { didSet { layer.cornerRadius = bounds.size.width / 2 }}
UIViewのサブクラスを作成し、layoutSubviewsをオーバーライドする
Swift 4キーパスKVO-これが自動回転とiPadサイドパネルへの移動を検出する方法です。どのようなビューでも機能するはずです。UIViewのレイヤーを監視する必要がありました。
private var observer: NSKeyValueObservation?
override func viewDidLoad() {
super.viewDidLoad()
observer = view.layer.observe(\.bounds) { object, _ in
print(object.bounds)
}
// ...
}
override func viewWillDisappear(_ animated: Bool) {
observer?.invalidate()
//...
}
.layer
トリックをした!を使用view.observe
しても機能しない理由を知っていますか?
UIViewのサブクラスを作成して、
setFrame:(CGRect)frame
方法。これは、ビューのフレーム(サイズ)が変更されたときに呼び出されるメソッドです。このようなことをしてください:
- (void) setFrame:(CGRect)frame
{
// Call the parent class to move the view
[super setFrame:frame];
// Do your custom code here.
}
setFrame:
にUITextView
サブクラスで呼び出されませんlayoutSubviews:
でした。注:自動レイアウトとiOS 7.0を使用しています。
setFrame:
。frame
派生プロパティです。私の答えをご覧ください
かなり古いですが、それでも良い質問です。Appleのサンプルコード、および一部のプライベートUIViewサブクラスでは、次のようにsetBoundsをオーバーライドします。
-(void)setBounds:(CGRect)newBounds {
BOOL const isResize = !CGSizeEqualToSize(newBounds.size, self.bounds.size);
if (isResize) [self prepareToResizeTo:newBounds.size]; // probably saves
[super setBounds:newBounds];
if (isResize) [self recoverFromResizing];
}
オーバーライドsetFrame:
はお勧めできません。frame
由来しcenter
、bounds
とtransform
、そうiOSのは、必ずしもコールすることはありませんsetFrame:
。
setBounds:
フレームプロパティを設定するときも呼び出されません(少なくともiOS 7.1では)。これは、Appleが追加メッセージを回避するために追加した最適化である可能性があります。
frame
とはbounds
、ビューの基礎となるから派生していますCALayer
。レイヤーのゲッターを呼び出すだけです。そしてsetFrame:
一方で、レイヤーのフレームを設定し、setBounds:
セット層の境界。したがって、どちらか一方をオーバーライドすることはできません。また、layoutSubviews
(ジオメトリの変更だけでなく)過度に呼び出されるため、必ずしも適切なオプションであるとは限りません。まだ探しています...
UIViewControllerインスタンスを使用viewDidLayoutSubviews
している場合は、オーバーライドすることでうまくいきます。
override func viewDidLayoutSubviews() {
// update subviews
}
UIView
インスタンスとUIViewController
インスタンスの関係に気づいたかもしれません。したがって、UIView
VCがアタッチされていないインスタンスがある場合、他の回答は素晴らしいですが、たまたまVCにアタッチされている場合、これはあなたの男です。申し訳ありませんが、お客様のケースには適用されません。