2014-11-05 39 views
1

在iOS 8.0中發現了一些有關自動佈局行爲的奇怪行爲,並且正在尋找任何提示或幫助解決此問題。我有一個UIView包含另一個UIView作爲包含兩個標籤的子視圖。這些標籤的約束條件如下所示:編程式自動佈局問題iOS 8.0

//StreamCaptionTextView.m 
    - (void)updateConstraints 
    { 
     NSDictionary *views = @{ 
           @"title" : self.titleLabel, 
           @"desc" : self.descLabel 
           }; 

     NSDictionary *metrics = @{ 
           @"top" : @0, 
           @"middle" : @(-2) 
           }; 

     [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[title]-0-|" options:0 metrics:metrics views:views]]; 
     [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[desc]-0-|" options:0 metrics:metrics views:views]]; 
     [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-top-[title]-middle-[desc(==title)]" options:0 metrics:metrics views:views]]; 

     [super updateConstraints]; 
    } 

此labelView的父視圖也對labelView具有約束。

//StreamCaptionView which contains the StreamCaptionTextView 
- (void)updateConstraints 
{ 
    [self removeConstraints:self.constraints]; 

    NSMutableDictionary *views = [[NSMutableDictionary alloc] initWithDictionary:@{ 
                       @"image" : self.profileImageBtn, 
                       @"leftView" : self.leftText 
                       }]; 
    NSDictionary *metrics = @{ 
          @"top"  : @6, 
          @"left"  : @8, 
          @"imageSize" : @24, 
          @"marginText" : @10, 
          @"maxWidth" : @120 
          }; 

    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-top-[image(imageSize)]" options:0 metrics:metrics views:views]]; 
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-top-[leftView]-top-|" options:0 metrics:metrics views:views]]; 

    if(self.rightAcessoryView) 
    { 
    views[@"rightView"] = self.rightAcessoryView ; 
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-left-[image(imageSize)]-2-[leftView]-10-[rightView(maxWidth)]-10-|" options:0 metrics:metrics views:views]]; 
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-top-[rightView]-top-|" options:0 metrics:metrics views:views]]; 
    } 
    else 
    { 
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-marginText-[image(imageSize)]-2-[leftView]-marginText-|" options:0 metrics:metrics views:views]]; 
    } 

    [super updateConstraints]; 
} 


//This is the View that contains the captionView 
- (void)setVo:(RecordingStreamItemVO *)vo 
    { 
     _vo = vo; 

     __weak RecordingDetailVideoView *_self = self; 

     self.captionView.title   = vo.user.screenname; 
     self.captionView.subTitle   = vo.title; 
     self.captionView.profileImageURL = vo.user.pictureURL; 

     //Here, the captionView is the rectangular blur, inside of the 
     //captionView is another UIView that contains the UILabels. 

    } 

由於某些原因,只有在iOS 8.0上,labelView才能正確呈現在labelView中。這在iOS 8.1和7.1等正常工作。我試圖使[self.labelView setNeedsUpdateConstraints]無效的約束,但這似乎並沒有 解決了這個問題。我已經使用了這一點,我已經看到其他人在iOS 8.0中有autoLayout問題,但想驗證這是否是iOS問題以及我可以實現的任何潛在解決方法。

Labels RenderingLabels Not Rendering

//這裏有一些照片顯示這是什麼樣子在Xcode可視化調試

//第一張照片是iOS 8.1中這是正常

enter image description here

//這張照片是在iOS 8.0上,似乎忽略了約束。

enter image description here

// IOS 8.0

layer = <CALayer: 0x17396c90>> 
    | | | | | | | | | | <StreamCaptionView: 0x15f1fe10; frame = (0 146; 320 35); layer = <CALayer: 0x15f2b3e0>> 
    | | | | | | | | | | | <UIButton: 0x15fcc240; frame = (10 6; 24 24); opaque = NO; layer = <CALayer: 0x15fcc340>> 
    | | | | | | | | | | | | <UIImageView: 0x1700d1c0; frame = (0 0; 24 24); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x1700d240>> 
    | | | | | | | | | | | <StreamCaptionTextView: 0x15fcc410; frame = (36 6; 274 23); layer = <CALayer: 0x15f2f620>> 
    | | | | | | | | | | | | <MarqueeLabel: 0x15f2f650; baseClass = UILabel; frame = (0 0; 274 13.5); text = 'test1'; clipsToBounds = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x15f200b0>> 
    | | | | | | | | | | | | | <UILabel: 0x17378d20; frame = (0 0; 26 0); text = 'test1'; userInteractionEnabled = NO; tag = 700; animations = { position=<CAKeyframeAnimation: 0x173b8960>; }; layer = <_UILabelLayer: 0x17378de0>> 
    | | | | | | | | | | | | | <UILabel: 0x173906b0; frame = (45 0; 22 0); text = 'test1'; userInteractionEnabled = NO; tag = 701; animations = { position=<CAKeyframeAnimation: 0x173b8a60>; }; layer = <_UILabelLayer: 0x17390770>> 
    | | | | | | | | | | | | <MarqueeLabel: 0x17390c40; baseClass = UILabel; frame = (0 11.5; 274 13.5); text = 'Test'; clipsToBounds = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x17390d60>> 
    | | | | | | | | | | | | | <UILabel: 0x17390940; frame = (0 0; 17 0); text = 'Test'; userInteractionEnabled = NO; tag = 700; animations = { position=<CAKeyframeAnimation: 0x173b93a0>; }; layer = <_UILabelLayer: 0x17390a00>> 
    | | | | | | | | | | | | | <UILabel: 0x173a1640; frame = (82 0; 48 0); text = 'Test'; userInteractionEnabled = NO; tag = 701; animations = { position=<CAKeyframeAnimation: 0x173b94a0>; }; layer = <_UILabelLayer: 0x173a1700>> 
    | | | | | | | | | <_UITableViewCellSeparatorView: 0x173ae010; frame = (15 179.5; 305 0.5); layer = <CALayer: 0x173ad1d0>> 
    | | | | | | | | <TimePublishedDetailView: 0x173a1d60; frame = (238.5 20; 71.5 11); layer = <CALayer: 0x173a1ef0>> 
    | | | | | | | | | <UIImageView: 0x173a21e0; frame = (0 0; 9 9); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x173a2260>> 
    | | | | | | | | | <UILabel: 0x173a85d0; frame = (16 -2; 55.5 13.5); text = '5 hours ago'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x173a8550>> 

更新:

其實我在父視圖控制器具有一個非常簡單的修補程序解決了這個。

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view. 

    [self.view addSubview:self.detailsView]; 
    [self.view setNeedsUpdateConstraints]; 
} 

- (void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 
    [self loadDetails]; 

    [self.view layoutIfNeeded]; //This fixed the iOS 8.0 problem 

} 

//In my case the self.detailsView property contains the view hierarchy which 
//contains the UILabels that weren't being rendered properly way down 
//in the view hierarchy. calling layoutIfNeeded fixes this problem for me. 
+0

我知道這是不是你正在尋找,但沒有試過的這一個? https://github.com/smileyborg/PureLayout它真的簡化了編寫約束的過程,並使讀取它的人更直觀 – 2014-11-05 19:47:26

+0

您是否嘗試使用View Debugger進行調試?您應該能夠看到究竟發生了什麼,視圖如何定位以及正在播放什麼約束 – sha 2014-11-05 19:54:43

+0

@sha我已經包含了Xcode所具有的可視調試器的一些照片。我可以看到,在iOS 8.0中,約束位置與8.1不同。 – zic10 2014-11-05 20:25:36

回答

0

首先,您需要確切地知道發生了什麼事。暫停應用在方便的點,並在控制檯中輸入以下命令:

po [[UIWindow keyWindow] recursiveDescription] 

如果這沒有幫助你立刻嘗試至少在這裏發佈它作爲我們的參考。

通常,執行手動佈局會導致佈局受到限制,或者Interface Builder會爲此發出警告。對於我沒有更多的調試信息,我仍然有點盲目。

現在我有那些我注意到以下行日誌:

| | | | | | | | | | | | | <UILabel: 0x17378d20; frame = (0 0; 26 0); text = 'test1'; userInteractionEnabled = NO; tag = 700; animations = { position=<CAKeyframeAnimation: 0x173b8960>; }; layer = <_UILabelLayer: 0x17378de0>> 
    | | | | | | | | | | | | | <UILabel: 0x173906b0; frame = (45 0; 22 0); text = 'test1'; userInteractionEnabled = NO; tag = 701; animations = { position=<CAKeyframeAnimation: 0x173b8a60>; }; layer = <_UILabelLayer: 0x17390770>> 

因此,所有的標籤似乎不具備的高度。

此行可能是關閉:

@"V:|-top-[title]-middle-[desc(==title)]" 

它似乎並沒有點擊底部,所以它不能給標題的高度,也沒有說明?試着做這樣的事情:

@"V:|-top-[title]-middle-[desc(==title)]-|" 

或給予最低高度:

@"V:|-top-[title(>=10)]-middle-[desc(==title)]" 
+0

它應該是在if語句下方的else語句中的行。 – zic10 2014-11-05 21:06:02

+0

謝謝您對我的建議,但不幸的是,他們沒有解決我的問題。這個視圖層次結構非常複雜,並且有很多部分。我意識到這只是一個更大的圖片的一小部分。我注意到的一件事是,在我的viewDidLoad中,我加載了這個視圖層次結構的所有屬性。但是,導航到另一個視圖控制器並返回將觸發viewWillAppear,並且在此場景中,標籤將在iOS 8.0上正確加載。我不確定這是否有幫助。 – zic10 2014-11-05 22:55:09

+0

當你做一個遞歸描述的時候,它在視覺樹中的區別是什麼,當它在viewWillAppear之後工作的時候呢? – 2014-11-06 02:49:09