2015-10-26 21 views
0

我是一種試圖進入自動佈局的深度。我有一個從故事板自動佈局工作的體面知識。此外,我知道如何使用NSLayoutConstraint類。 這裏是問題:我有2個視圖(redView和yellowView)。從storyboard中,我已經設置了兩個視圖的約束。現在在我的代碼中,假設我想改變redView的寬度和黃色寬度。所以我用下面的代碼爲:Autolay編程

NSLayoutConstraint *layouts1 = [NSLayoutConstraint 
           constraintWithItem:_redView 
           attribute:NSLayoutAttributeWidth 
           relatedBy:NSLayoutRelationEqual 
           toItem:_yellowView 
           attribute:NSLayoutAttributeWidth 
           multiplier:3.0f 
           constant:0]; 
[self.view addConstraint:layouts1]; 

現在我運行的代碼,雖然我得到預期的輸出,它表明「不可滿足約束」在控制檯上的消息(這應該是因爲多個寬度被設定)。現在的問題是:我怎麼能擺脫這個消息? 我已經嘗試了幾件事情,但他們不是working.Here是我曾嘗試:

  1. 我沒有設置約束我直接與下面的代碼工作的storyboard.Instead。
  2. 我試着用'layoutIfNeeded'這個方法。

嗯,我可以通過編程寫全自動佈局代碼,但由於我們有幸通過故事板設置自動佈局,它是完全unnecessary.There一定有辦法只是爲了更新約束(分鏡腳本集)無需編程得到任何衝突。

+0

如果你想設置紅視等寬度的黃色視圖,那麼你可以使用平等寬度爲靜態。但是在寬度變化的情況下,您需要將寬度約束連接到代碼,並且您可以更改d常量值 – iApple

+0

但是,如果在設置相等寬度後再編寫上面的代碼,我會面臨同樣的問題。只要想一想就可以了。 – Reckoner

+0

這是一個很好的post-anchor風格,在iOS 9中是一個救生員http://stackoverflow.com/questions/26180822/swift-adding-constraints-programmatically/26181982#26181982 – DogCoffee

回答

0

那麼我明白我在做什麼。因爲我已經在故事板中設置了約束條件,我需要移除寬度約束(在故事板中)以使用新約束來更新它。我剛剛創建了一個IBOutlet我yellowView的寬度,然後這個代碼並獲得成功對我來說:

[_yellowView removeConstraint:_myConstraints];//_myConstraints is the outlet 

現在我不能正確,當你面對任何problem.Thanks很多人:-)

+0

不客氣;) – ullstrm

+0

我已經回答了我的評論。如果你認爲這是你的問題的答案,你可以接受它。 – ullstrm

+0

@Spoek解決這個問題的另一種方法,所以我的知識庫收益:-) – Reckoner

1

難道我理解你想要以編程方式編輯現有約束?即從故事板設置的約束?

您可以從約束中創建一個IBOutlet,並以編程方式設置它的constant -property。然後致電layotIfNeeded

0

MARK: - 查找約束

- (NSLayoutConstraint *)myConstraintWithAttribute:(NSLayoutAttribute)attribute 
{ 
    /* Find constraint with attribute in my constraints */ 
    __block NSLayoutConstraint *resultConstraint; 
    [self.constraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *constraint, NSUInteger idx, BOOL *stop) 
    { 
     // DebugLog(@"constraint %@", constraint); 
     if ([NSStringFromClass([NSLayoutConstraint class]) isEqualToString:NSStringFromClass([constraint class])]) 
     { 
      if (constraint.firstAttribute == attribute || constraint.secondAttribute == attribute) 
      { 
       resultConstraint = constraint; 
       *stop = YES; 
      } 
     } 
    }]; 

    return resultConstraint; 
} 


- (NSLayoutConstraint *)superviewConstraintWithAttribute:(NSLayoutAttribute)attribute 
{ 
    /* Find constraint with attribute in my superview's constraints */ 
    __block NSLayoutConstraint *resultConstraint; 
    [self.superview.constraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *constraint, NSUInteger idx, BOOL *stop) 
    { 
     if (constraint.firstItem == self && constraint.firstAttribute == attribute) 
      //|| (constraint.secondItem == self && constraint.secondAttribute == attribute)) 
     { 
      resultConstraint = constraint; 
      *stop = YES; 
     } 
    }]; 

    return resultConstraint; 
} 


- (NSLayoutConstraint *)constraintWithAttribute:(NSLayoutAttribute)attribute 
{ 
    /* Find constraint with attribute in my constraints */ 
    NSLayoutConstraint *resultConstraint = [self myConstraintWithAttribute:attribute]; 

    /* Find constraint with attribute in my superview's constraints */ 
    if (!resultConstraint) 
    { 
     resultConstraint = [self superviewConstraintWithAttribute:attribute]; 
    } 
    return resultConstraint; 
} 


- (BOOL)removeConstraintWithAttribute:(NSLayoutAttribute)attribute 
{ 
    NSLayoutConstraint *constraint = [self superviewConstraintWithAttribute:attribute]; 
    if (constraint) 
    { 
     [self.superview removeConstraint:constraint]; 
     return YES; 
    } 
    constraint = [self myConstraintWithAttribute:attribute]; 
    if (constraint) 
    { 
     [self removeConstraint:constraint]; 
     return YES; 
    } 
    return NO; 
} 

MARK: - 刪除約束

- (void)removeMyConstraints 
{ 
    /* Remove all my constraitns from superview */ 
    [self.superview removeConstraints:[self mySuperviewConstraints]]; 

    /* Remove my constraitns */ 

    [self removeConstraints:self.constraints]; 
} 


- (NSArray *)mySuperviewConstraints 
{ 
    NSMutableArray *mySuperviewConstraints = [NSMutableArray array]; 
    [self.superview.constraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *constraint, NSUInteger idx, BOOL *stop) 
    { 
     if (constraint.firstItem == self || constraint.secondItem == self) 
     { 
      [mySuperviewConstraints addObject:constraint]; 
     } 
    }]; 
    return mySuperviewConstraints; 
} 


- (void)removeMyConstraintsButKeepMySubviewConstraints 
{ 
    /* Remove all my constraitns from superview */ 
    [self.superview removeConstraints:[self mySuperviewConstraints]]; 

    /* Remove my constraitns */ 

    [self removeConstraints:[self myConstraints]]; 
} 


- (NSArray *)myConstraints 
{ 
    NSMutableArray *myConstraints = [NSMutableArray array]; 
    [self.constraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *constraint, NSUInteger idx, BOOL *stop) 
    { 
     if (constraint.firstItem == self && constraint.secondItem == nil) 
     { 
      [myConstraints addObject:constraint]; 
     } 
    }]; 
    return myConstraints; 
} 

MARK: - 大小限制

- (void)addWidthConstraint:(CGFloat)width 
{ 
    NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self 
                    attribute:NSLayoutAttributeWidth 
                    relatedBy:NSLayoutRelationEqual 
                    toItem:nil 
                    attribute:0 
                   multiplier:1 
                    constant:width]; 
    [self addConstraint:constraint]; 
} 

- (void)addWidthConstraintFromLabel:(UILabel *)label 
         withOffset:(CGFloat)offset 
{ 
    NSDictionary *attributes = @{NSFontAttributeName : label.font}; 
    return [self addWidthConstraint:[label.text sizeWithAttributes:attributes].width + offset]; 
} 

- (void)addHeightConstraint:(CGFloat)height 
{ 
    NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self 
                    attribute:NSLayoutAttributeHeight 
                    relatedBy:NSLayoutRelationEqual 
                    toItem:nil 
                    attribute:0 
                   multiplier:1 
                    constant:height]; 
    [self addConstraint:constraint]; 
} 

- (void)addMaximumHeightConstraint:(CGFloat)maxHeight 
{ 
    NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self 
                    attribute:NSLayoutAttributeHeight 
                    relatedBy:NSLayoutRelationLessThanOrEqual 
                    toItem:nil 
                    attribute:0 
                   multiplier:1 
                    constant:maxHeight]; 
    [self addConstraint:constraint]; 

} 


- (void)addWidthConstraintFromImage:(UIImage *)image 
{ 
    [self addWidthConstraint:image.size.width]; 
} 


- (void)addHeightConstraintFromImage:(UIImage *)image 
{ 
    [self addHeightConstraint:image.size.height]; 
} 

MARK: - 中心約束上

- (void)addCenterConstraint:(UIView *)view 
      centerDirection:(NSLayoutAttribute)centerDirection 
        offset:(CGFloat)offset 
{ 
    UIView *viewItem = (view) ? view : self.superview; 
    NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self 
                    attribute:centerDirection 
                    relatedBy:NSLayoutRelationEqual 
                    toItem:viewItem 
                    attribute:centerDirection 
                   multiplier:1 
                    constant:offset]; 
    [self.superview addConstraint:constraint]; 
} 


- (void)addCenterXConstraint:(UIView *)view 
{ 
    [self addCenterConstraint:view 
       centerDirection:NSLayoutAttributeCenterX 
         offset:0]; 
} 


- (void)addCenterYConstraint:(UIView *)view 
{ 
    [self addCenterConstraint:view 
       centerDirection:NSLayoutAttributeCenterY 
         offset:0]; 
} 


- (void)addCenterXConstraint:(UIView *)view 
         offset:(CGFloat)offset 
{ 
    [self addCenterConstraint:view 
       centerDirection:NSLayoutAttributeCenterX 
         offset:offset]; 
} 


- (void)addCenterYConstraint:(UIView *)view 
         offset:(CGFloat)offset 
{ 
    [self addCenterConstraint:view 
       centerDirection:NSLayoutAttributeCenterY 
         offset:offset]; 
} 

MARK: - 邊連接約束

- (void)addEdgeAttachConstraint:(UIView *)view 
         viewEdge:(NSLayoutAttribute)viewLayoutAttribute 
         offset:(CGFloat)offset 
          edge:(NSLayoutAttribute)layoutAttribute 
{ 
    UIView *viewItem = (view) ? view : self.superview; 

    /* Reverse offset for right side and bottom */ 
    CGFloat fixedOffset = offset; 
    if (layoutAttribute == NSLayoutAttributeRight 
     || layoutAttribute == NSLayoutAttributeBottom 
     || layoutAttribute == NSLayoutAttributeTrailing) 
    { 
     fixedOffset = -offset; 
    } 

    /* Add contraint */ 
    NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self 
                    attribute:layoutAttribute 
                    relatedBy:NSLayoutRelationEqual 
                    toItem:viewItem 
                    attribute:viewLayoutAttribute 
                   multiplier:1 
                    constant:fixedOffset]; 
    [self.superview addConstraint:constraint]; 
} 




- (void)addLeftEdgeAttachConstraint:(UIView *)view 
          offset:(CGFloat)offset 
{ 
    [self addEdgeAttachConstraint:view 
         viewEdge:NSLayoutAttributeLeft 
          offset:offset 
          edge:NSLayoutAttributeLeft]; 
} 


- (void)addRightEdgeAttachConstraint:(UIView *)view 
           offset:(CGFloat)offset 
{ 
    [self addEdgeAttachConstraint:view 
         viewEdge:NSLayoutAttributeRight 
          offset:offset 
          edge:NSLayoutAttributeRight]; 
} 


- (void)addTopEdgeAttachConstraint:(UIView *)view 
          offset:(CGFloat)offset 
{ 
    [self addEdgeAttachConstraint:view 
         viewEdge:NSLayoutAttributeTop 
          offset:offset 
          edge:NSLayoutAttributeTop]; 
} 


- (void)addBottomEdgeAttachConstraint:(UIView *)view 
           offset:(CGFloat)offset 
{ 
    [self addEdgeAttachConstraint:view 
         viewEdge:NSLayoutAttributeBottom 
          offset:offset 
          edge:NSLayoutAttributeBottom]; 
} 




- (void)addLeftEdgeAttachConstraint:(UIView *)view 
{ 
    [self addLeftEdgeAttachConstraint:view 
           offset:0]; 
} 


- (void)addRightEdgeAttachConstraint:(UIView *)view 
{ 
    [self addRightEdgeAttachConstraint:view 
           offset:0]; 
} 


- (void)addTopEdgeAttachConstraint:(UIView *)view 
{ 
    [self addTopEdgeAttachConstraint:view 
           offset:0]; 
} 


- (void)addBottomEdgeAttachConstraint:(UIView *)view 
{ 
    [self addBottomEdgeAttachConstraint:view 
           offset:0]; 
} 




- (void)addEdgeAttachConstraints:(UIView *)view 
         leftOffset:(CGFloat)leftOffset 
        rightOffset:(CGFloat)rightOffset 
         topOffset:(CGFloat)topOffset 
        bottomOffset:(CGFloat)bottomOffset 
{ 
    [self addLeftEdgeAttachConstraint:view 
           offset:leftOffset]; 
    [self addRightEdgeAttachConstraint:view 
           offset:rightOffset]; 
    [self addTopEdgeAttachConstraint:view 
           offset:topOffset]; 
    [self addBottomEdgeAttachConstraint:view 
           offset:bottomOffset]; 
} 


- (void)addEdgeAttachConstraints:(UIView *)view 
{ 
    [self addLeftEdgeAttachConstraint:view]; 
    [self addRightEdgeAttachConstraint:view]; 
    [self addTopEdgeAttachConstraint:view]; 
    [self addBottomEdgeAttachConstraint:view]; 
} 

MARK: - 邊緣約束的不同的邊緣

- (void)addLeftEdgeAttachConstraint:(UIView *)view 
          viewEdge:(NSLayoutAttribute)viewLayoutAttribute 
          offset:(CGFloat)offset 
{ 
    [self addEdgeAttachConstraint:view 
         viewEdge:viewLayoutAttribute 
          offset:offset 
          edge:NSLayoutAttributeLeft]; 
} 


- (void)addRightEdgeAttachConstraint:(UIView *)view 
          viewEdge:(NSLayoutAttribute)viewLayoutAttribute 
           offset:(CGFloat)offset 
{ 
    [self addEdgeAttachConstraint:view 
         viewEdge:viewLayoutAttribute 
          offset:offset 
          edge:NSLayoutAttributeRight]; 
} 


- (void)addTopEdgeAttachConstraint:(UIView *)view 
          viewEdge:(NSLayoutAttribute)viewLayoutAttribute 
          offset:(CGFloat)offset 
{ 
    [self addEdgeAttachConstraint:view 
         viewEdge:viewLayoutAttribute 
          offset:offset 
          edge:NSLayoutAttributeTop]; 
} 


- (void)addBottomEdgeAttachConstraint:(UIView *)view 
          viewEdge:(NSLayoutAttribute)viewLayoutAttribute 
           offset:(CGFloat)offset 
{ 
    [self addEdgeAttachConstraint:view 
         viewEdge:viewLayoutAttribute 
          offset:offset 
          edge:NSLayoutAttributeBottom]; 
} 

MARK: - 尺寸附加Constai NTS

- (void)addSizeAndSuperviewAttachConstraints:(NSString *)sizeConstraint 
           firstOffset:(CGFloat)firstOffset 
           secondOffset:(CGFloat)secondOffset 
            direction:(NSString *)direction 
{ 
    NSDictionary *viewDict = NSDictionaryOfVariableBindings(self); 
    NSString *visualFormatString; 

    if (sizeConstraint) 
    { 
     visualFormatString = [NSString stringWithFormat:@"%@:|-%f-[self(%@)]-%f-|", direction, firstOffset, sizeConstraint, secondOffset]; 
    } 
    else 
    { 
     visualFormatString = [NSString stringWithFormat:@"%@:|-%f-[self]-%f-|", direction, firstOffset, secondOffset]; 
    } 

    NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:visualFormatString 
                    options:0 
                    metrics:0 
                    views:viewDict]; 
    [self.superview addConstraints:constraints]; 
} 


- (void)addWidthAndSuperviewAttachConstraints:(NSString *)widthConstraint 
            leftOffset:(CGFloat)leftOffset 
            rightOffset:(CGFloat)rightOffset 
{ 
    [self addSizeAndSuperviewAttachConstraints:widthConstraint 
            firstOffset:leftOffset 
            secondOffset:rightOffset 
            direction:@"H"]; 
} 


- (void)addHeightAndSuperviewAttachConstraints:(NSString *)heightConstraint 
            topOffset:(CGFloat)topOffset 
            bottomOffset:(CGFloat)bottomOffset 
{ 
    [self addSizeAndSuperviewAttachConstraints:heightConstraint 
            firstOffset:topOffset 
            secondOffset:bottomOffset 
            direction:@"V"]; 
} 

MARK: - 行&列布局約束

- (void)addLayoutConstraintsForMySubviews:(NSArray *)views 
           firstOffset:(CGFloat)firstOffset 
          secondOffset:(CGFloat)secondOffset 
          betweenOffset:(NSString *)betweenOffset 
           direction:(NSString *)direction 
           equalSize:(BOOL)equalSize 
{ 
    /* Create viewDict and visualFormatString */ 
    NSMutableString *visualFormatString = [[NSMutableString alloc] initWithFormat:@"%@:|-%.0f-", direction, firstOffset]; 
    NSMutableDictionary *viewDict = [[NSMutableDictionary alloc] init]; 
    [views enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL *stop) 
    { 
     NSString *viewName = [NSString stringWithFormat:@"view%i", idx]; 
     [viewDict setObject:view 
         forKey:viewName]; 

     if (idx < [views count] - 1) 
     { 
      /* Add each view */ 
      if (betweenOffset) /* Add offset between view */ 
      { 
       /* Add equal size to prev view for all but index 0 */ 
       if (equalSize && idx > 0) 
       { 
        NSString *prevViewName = [NSString stringWithFormat:@"view%i", idx - 1]; 
        [visualFormatString appendFormat:@"[%@(==%@)]-%@-", viewName, prevViewName, betweenOffset]; 
       } 
       else 
       { 
        [visualFormatString appendFormat:@"[%@]-%@-", viewName, betweenOffset]; 
       } 
      } 
      else /* No offset between views */ 
      { 
       /* Add equal size to prev view for all but index 0 */ 
       if (equalSize && idx > 0) 
       { 
        NSString *prevViewName = [NSString stringWithFormat:@"view%i", idx - 1]; 
        [visualFormatString appendFormat:@"[%@(==%@)]", viewName, prevViewName]; 
       } 
       else 
       { 
        [visualFormatString appendFormat:@"[%@]", viewName]; 
       } 
      } 
     } 
     else 
     { 
      /* Add equal size to prev view for all but index 0 */ 
      if (equalSize && idx > 0) 
      { 
       NSString *prevViewName = [NSString stringWithFormat:@"view%i", idx - 1]; 
       [visualFormatString appendFormat:@"[%@(==%@)]-%.0f-|", viewName, prevViewName, secondOffset]; 
      } 
      else 
      { 
       [visualFormatString appendFormat:@"[%@]-%.0f-|", viewName, secondOffset]; 
      } 
     } 
    }]; 

    // DebugLog(@"viewDict %@", viewDict); 
    // DebugLog(@"visualFormatString %@", visualFormatString); 

    /* Add constraints */ 
    NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:visualFormatString 
                    options:0 
                    metrics:0 
                    views:viewDict]; 
    [self addConstraints:constraints]; 
} 


- (void)addRowLayoutConstraintsForMySubviews:(NSArray *)subviews 
            leftOffset:(CGFloat)leftOffset 
           rightOffset:(CGFloat)rightOffset 
           betweenOffset:(NSString *)betweenOffset 
            equalWidth:(BOOL)equalWidth 
{ 
    [self addLayoutConstraintsForMySubviews:subviews 
           firstOffset:leftOffset 
           secondOffset:rightOffset 
           betweenOffset:betweenOffset 
            direction:@"H" 
            equalSize:equalWidth]; 
} 


- (void)addColumnLayoutConstraintsForMySubviews:(NSArray *)subviews 
             topOffset:(CGFloat)topOffset 
            bottomOffset:(CGFloat)bottomOffset 
            betweenOffset:(NSString *)betweenOffset 
            equalHeight:(BOOL)equalHeight 
{ 
    [self addLayoutConstraintsForMySubviews:subviews 
           firstOffset:topOffset 
           secondOffset:bottomOffset 
           betweenOffset:betweenOffset 
            direction:@"V" 
            equalSize:equalHeight]; 
} 

MARK: - 行&列大小相等佈局約束

- (void)addEqualSizeLayoutConstraintsForMySubviews:(NSArray *)views 
             firstOffset:(CGFloat)firstOffset 
             secondOffset:(CGFloat)secondOffset 
            betweenOffset:(NSString *)betweenOffset 
             direction:(NSString *)direction 
{ 
    /* Create viewDict and visualFormatString */ 
    NSMutableString *visualFormatString = [[NSMutableString alloc] initWithFormat:@"%@:|-%.0f-", direction, firstOffset]; 
    NSMutableDictionary *viewDict = [[NSMutableDictionary alloc] init]; 
    [views enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL *stop) 
    { 
     NSString *viewName = [NSString stringWithFormat:@"view%i", idx]; 
     [viewDict setObject:view 
         forKey:viewName]; 

     if (idx < [views count] - 1) 
     { 
      if (betweenOffset) 
      { 
       [visualFormatString appendFormat:@"[%@]-%@-", viewName, betweenOffset]; 
      } 
      else 
      { 
       [visualFormatString appendFormat:@"[%@(>=40)]", viewName]; 
      } 
     } 
     else 
     { 
      [visualFormatString appendFormat:@"[%@(>=40)]-%.0f-|", viewName, secondOffset]; 
     } 
    }]; 


    // DebugLog(@"viewDict %@", viewDict); 

    /* Add constraints */ 
    NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[view0]-2-[view1(==view0)]-2-[view2(==view1)]-2-[view3(==view2)]-2-[view4(==view3)]-2-[view5(==view4)]-0-|" 
                    options:0 
                    metrics:0 
                    views:viewDict]; 
    [self addConstraints:constraints]; 
} 


- (void)addRowLayoutEqualWidthConstraintsForMySubviews:(NSArray *)subviews 
              leftOffset:(CGFloat)leftOffset 
              rightOffset:(CGFloat)rightOffset 
             betweenOffset:(NSString *)betweenOffset 
{ 
    [self addEqualSizeLayoutConstraintsForMySubviews:subviews 
             firstOffset:leftOffset 
             secondOffset:rightOffset 
             betweenOffset:betweenOffset 
              direction:@"H"]; 
}