2017-07-16 116 views
0

我必須改變約束,但通過改變約束常量, 我得到重複 - Xcode提供了一個警告。改變約束常量的正確方法是什麼

我可以看到,一個約束是舊的,另一個是新的,它們的內存地址是不同的。

創建和設置視圖以處理約束更改的正確方法是什麼?

我的例子我有一個mainView添加到self.view,提供的視圖 當你擴展UIViewController。提供「self.view」並且沒有設置約束。

Main MainView是我的容器,每當鍵盤出現時我都想調整它的高度使其位於鍵盤上方。

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被再次調用並重新創建CON straints。 如何在不重新創建的情況下更改約束條件?或者這裏使用的正確模式是什麼。

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]; 
} 

原木

約束1在存儲器地址0x174286450

約束2在存儲器地址0x174288660

(
"<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兩次。首先,您創建一個_mainBottomContraint並保留它,當鍵盤更改,_mainBottomContraint.constaints更改,並且self.view.subviews中的視圖更改框架時,系統會發佈一個通知,並且viewcontroller會收到它,然後調用viewWillLayoutSubviews,就像view將調用layoutSubviews一樣。所以你創建一個_mainBottomContraint,所以現在有兩個bottomContraint,你會得到一個警告。 您應該添加約束上只有一次,你可以在viewDidLoad中函數添加它們,這將是很好。

+0

謝謝Zacks。將我的約束初始化移至viewDidLoad可修復此錯誤。但我想知道正確的模式是什麼。 那你把裏面的「viewWillLayoutSubviews」 - 蘋果醫生說「......當一個視圖邊界的變化,認爲調整其子視圖的位置......」。 所以我改變了「界限」使用自動佈局。使用自動佈局時,此方法是否有用? 仍尋求創建視圖,鋪出來的跳轉模式。 – Wayne

+0

同意。只創建一次。 viedDidLoad是最好的地方。要只更新更改常量(您可以動畫) –

+0

下面的兩個答案將解決它。兩者都是必要的。我從來不需要覆蓋方法viewWillLayoutSubviews。用一次約束創建你的視圖。在添加之前請確保調用translatesAutoresizingMaskIntoConstraints。 –

相關問題