2017-07-16 23 views
0

制約を変更する必要がありますが、制約定数を変更することによって 重複が発生します.Xcodeは警告を出します。制約定数を変更する正しい方法は何ですか

1つの制約が古いもので、もう1つが新しいものであることがわかります。 とそのメモリアドレスが異なります。

制約の変更を処理するビューを作成および設定する正しい方法は何ですか?

私の例では、UIViewControllerを拡張するときに、self.viewに提供されたビュー を追加したmainViewがあります。 "self.view"が提供され、制約が設定されていません。

メインのメインビューはコンテナで、キーボードが表示されるたびにキーボードの高さに合わせて高さを調整します。

のviewDidLoad:

- (void)viewDidLoad { 

    [super viewDidLoad]; 

    _mainView = [UIView new]; 
    _mainView.translatesAutoresizingMaskIntoConstraints = NO; 
    [self.view addSubview:_mainView]; 
} 

viewWillLayoutSubviews:

-(void)viewWillLayoutSubviews { 

[super viewWillLayoutSubviews]; 

//moved to viewDidLoad 
//self.mainView.translatesAutoresizingMaskIntoConstraints = NO; 

//top 
[[self view] addConstraint:[NSLayoutConstraint constraintWithItem:_mainView 
                 attribute:NSLayoutAttributeTop 
                 relatedBy:NSLayoutRelationEqual 
                  toItem:self.view 
                 attribute:NSLayoutAttributeTop 
                 multiplier:1.0 
                 constant:0]]; 

//bottom 
_mainBottomContraint = [NSLayoutConstraint constraintWithItem:_mainView 
                attribute:NSLayoutAttributeBottom 
                relatedBy:NSLayoutRelationEqual 
                 toItem:self.view 
                attribute:NSLayoutAttributeBottom 
                multiplier:1.0 
                constant:_keyboardOffset]; 

[[self view] addConstraint:_mainBottomContraint]; 

//left 
[[self view] addConstraint:[NSLayoutConstraint constraintWithItem:_mainView 
                 attribute:NSLayoutAttributeLeft 
                 relatedBy:NSLayoutRelationEqual 
                  toItem:self.view 
                 attribute:NSLayoutAttributeLeft 
                 multiplier:1.0 
                 constant:0]]; 

//right 
[[self view] addConstraint:[NSLayoutConstraint constraintWithItem:_mainView 
                 attribute:NSLayoutAttributeRight 
                 relatedBy:NSLayoutRelationEqual 
                  toItem:self.view 
                 attribute:NSLayoutAttributeRight 
                 multiplier:1.0 
                 constant:0]]; 

-

私は、制約の定数を変更するたびに、私は、重複制約を取得し、 viewWillLayoutSubviewsが再び呼ばれ、再作成されますコンひずみ。 再作成せずに制約をどのように変更しますか?または、ここで使用する正しいパターンは何か。

keyboardWillShow - メモリアドレスに制約(setConstant)

- (void)keyboardWillShow:(NSNotification*)aNotification { 

    if (![_chatTextField isFirstResponder]) { 
     return; 
    } 

    CGSize tabBarSize = [[[self tabBarController] tabBar] bounds].size;  
    NSDictionary* info = [aNotification userInfo]; 

    NSTimeInterval duration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; 
    UIViewAnimationCurve curve = [[info objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]; 

    CGSize kbSize = [info[UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; 

    CGRect bkgndRect = _mainView.frame; 
    bkgndRect.size.height -= kbSize.height-tabBarSize.height; 

    //animate with keyboard 
    _keyboardOffset = -kbSize.height-tabBarSize.height; 
    [_mainBottomContraint setConstant:_keyboardOffset]; 
    [self.view setNeedsLayout]; 

    [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState | curve  animations:^{ 
     [_mainView layoutIfNeeded]; 

    } completion:nil]; 
} 

LOGS

制約1を変更0x174286450

制約2メモリアドレス0x174288660

0123でサブビューの
(
"<NSLayoutConstraint:0x174286450 UIView:0x14fd5e5b0.bottom == UIView:0x14fe5edd0.bottom - 271 (active)>", 
"<NSLayoutConstraint:0x174288660 UIView:0x14fd5e5b0.bottom == UIView:0x14fe5edd0.bottom (active)>" 
) 

答えて

0

コール

subview.translatesAutoresizingMaskIntoConstraints = NO; 

別のビューに追加する前に。さもなければ、いくつかの制約が自動的に作成され、警告につながります。

- (void)viewDidLoad { 
[super viewDidLoad]; _mainView = [UIView new]; 
self.mainView.translatesAutoresizingMaskIntoConstraints = NO; 

[self.view addSubview:_mainView]; 
} 

作成した制約の参照を保存し、必要に応じて変更します。

+0

私はまだ重複を取得しています、私はviewDidLoadを更新して、あなたが言及したようにそれらを追加する前にマスクを制約に加えます。 質問をログで更新します。 – Wayne

+0

あなたの提案で私の質問を更新しました。 – Wayne

1

私の意見では、_mainBottomContraintを2回追加します。まず、_mainBottomContraintを作成し、キーボードの変更、_mainBottomContraint.constaintsの変更、およびself.view.subviewsのビューがフレームを変更した場合は保持します。システムは通知をポストし、viewcontrollerはそれを受け取り、viewWillLayoutSubviewsを呼び出します。ビューはlayoutSubviews.Soを呼び出すので、_mainBottomContraintを作成します。したがって、bottomContraintが2つあり、警告が表示されます。 contraintsを一度だけ追加する必要があります。それらをviewDidLoad関数で追加すると良いでしょう。

+0

おかげさまでザック。制約の初期化をviewDidLoadに移すと、バグが修正されます。しかし、私は正しいパターンが何であるか疑問に思います。 "viewWillLayoutSubviews"の中に何を入れますか - Apple docは "....ビューの境界が変わると、ビューはそのサブビューの位置を調整します...." 自動レイアウトを使用して「境界」を変更しています。自動レイアウトを使用する場合、このメソッドには使用されていますか? ビューを作成しレイアウトするためのgotoパターンを探しています。 – Wayne

+0

が同意します。一度だけ作成してください。 viedDidLoadは最適な場所です。両方の答えに続く –

+0

の変更定数(アニメートできる)だけを更新するには、それを修正します。どちらも必要です。私はviewWillLayoutSubviewsメソッドを上書きする必要はありませんでした。一度すべての制約でビューを作成してください。追加する前に必ずtranslatesAutoresizingMaskIntoConstraintsを呼び出してください。 –

関連する問題