2013-10-28 57 views
10

我正在構建一個複雜的項目,其中,我需要將UIPageViewController設置爲主視圖的子視圖。我使用自動佈局,並使用約束來對主視圖上的各種元素進行排序。在UIPageViewController上將TranslatesAutoresizingMaskIntoConstraints設置爲No

問題是,當我嘗試運行該應用程序時,由於衝突NSAutoresizingMaskLayoutConstraints而導致崩潰。

2013-10-28 16:22:18.419 Red Event App[1658:60b] Unable to simultaneously satisfy constraints. 
Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
"<NSLayoutConstraint:0x145c1990 V:|-(20)-[UINavigationBar:0x145bf6b0] (Names: '|':UIView:0x145bf620)>", 
"<NSLayoutConstraint:0x145bf510 V:[UINavigationBar:0x145bf6b0]-(0)-[UIView:0x145bef70]>", 
"<NSLayoutConstraint:0x145d0550 UIView:0x145a8c10.top == UIView:0x145bf620.top>", 
"<NSAutoresizingMaskLayoutConstraint:0x145b3a40 h=-&- v=-&- UIView:0x145a8c10.midY == UIView:0x145bef70.midY + 56.5>", 
"<NSAutoresizingMaskLayoutConstraint:0x145b3a70 h=-&- v=-&- UIView:0x145a8c10.height == UIView:0x145bef70.height + 113>" 
) 

通常的治療方法是將TranslatesAutoresizingMaskIntoConstraints設置爲no。

但是,當我這樣做時,UIPageViewController的子視圖開始忽略PageViewController的邊界,並以(0,0)的原點結束(據我所知)。

我已經嘗試通過手動設置幀都設置最多時的數據源(_itemViewControllers)以固定的位置:

- (void)setupLeafs{ 
    _itemViewControllers = [[NSMutableArray alloc]init]; 
    for(NSString *pagename in _datasource){ 
     RWNode *page = [_xml getPage:pagename]; 
     UIViewController *viewController = [RWNavigationController getViewControllerFromDictionary:[page getDictionaryFromNode]]; 
     viewController.view.frame = CGRectMake(self.view.frame.origin.x,self.view.frame.origin.y,self.view.frame.size.width, self.view.frame.size.height); 

     [_itemViewControllers addObject:viewController]; 
    } 
} 

並獲得當頁面

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController { 
    UIViewController *nextViewController = [self getPreviousLeaf:viewController]; 
    nextViewController.view.frame = CGRectMake(self.view.frame.origin.x,self.view.frame.origin.y,self.view.frame.size.width, self.view.frame.size.height); 
    return nextViewController; 
} 

但也有任何效果。

我需要約束我正在做什麼,所以堅持面具不是一種選擇。我想我正在尋找的是一種在添加UIPageViewController子項後(通過任何進程調用viewControllerBeforeViewController)對其進行約束的方法。但我真的很想聽聽解決這個問題的方法。

編輯: 我發現了一個黑客來解決這個問題。我不太確定我在這裏列出的是整個解決方案,但這是我現在注意到的,經過一個多月的修補代碼之後。

首先,在樹立pageviewcontroller視圖控制器,我有以下兩行,我已經初始化pageviewcontroller

UIView *pageView = self.pageViewController.view; 
pageView.frame = self.view.frame; 

不,我已經在這個視圖控制器設置[self.view setTranslatesAutoresizingMaskIntoConstraints:NO];之後。

其次,在子控制器上,我檢查視圖是在pageviewcontroller內部還是外部使用。只有在瀏覽控制器中使用而不是時,纔會在子視圖上設置[self.view setTranslatesAutoresizingMaskIntoConstraints:NO];

現在,這個工作(對我來說)目前。但我真的很喜歡一個不太冒險的解決方案。

+0

這次事故可能是由於其他原因。如果發生衝突約束,通常會忽略其中的一個(並記錄事實)。你能粘貼整個堆棧跟蹤嗎? –

+0

它說(舉個例子): 「將嘗試打破約束,以恢復 歇上objc_exception_throw趕上這在調試器。 中列出的UIView上的UIConstraintBasedLayoutDebugging類別中的方法也可能有所幫助。「 但是除此之外沒有相關的日誌消息。它發出這條消息後確實崩潰了。 – Rubberduck

+0

你能描述一下你想要實現的目標嗎?這將是非常有用的,以提供任何形式的建議:) –

回答

2

我不能給你答案,但也許我可以給你一些調試建議。將日誌信息複製到文本編輯器中,並用有意義的名稱替換視圖的內存地址信息。 (使用調試器查找存儲器地址映射到哪些屬性,如果你不知道)。然後你會發現它更容易理解日誌信息並追蹤衝突。下面是一個例子(雖然我只是猜測您的視圖層次)

"<NSLayoutConstraint:0x145c1990 V:|-(20)-[UINavigationBar:NAVBAR] (Names: '|':UIView:ROOTVIEW)>", 
"<NSLayoutConstraint:0x145bf510 V:[UINavigationBar:NAVBAR]-(0)-[UIView:PAGECONTAINER]>", 
"<NSLayoutConstraint:0x145d0550 UIView:PAGEVIEW.top == UIView:ROOTVIEW.top>", 
"<NSAutoresizingMaskLayoutConstraint:0x145b3a40 h=-&- v=-&- UIView:PAGEVIEW.midY == UIView:PAGECONTAINER.midY + 56.5>", 
"<NSAutoresizingMaskLayoutConstraint:0x145b3a70 h=-&- v=-&- UIView:PAGEVIEW.height == UIView:PAGECONTAINER.height + 113>" 

在猜測,最後兩個autoresizingmasklayoutconstraints看起來很奇怪我,他們不看明確規定。

+0

我的問題不是真正的約束。我知道這是造成問題的AutoresizingMaskLayoutConstraints。問題是,刪除AutoresizingMaskLayoutConstraint的方法是將TranslatesAutoresizingMaskIntoConstraints設置爲no。當我這樣做時,如果它們位於UIPageViewController中,它會將視圖搞砸。這是我的問題。 – Rubberduck

6

使用AutoLayout時,不應該直接設置視圖的框架。約束被用來爲你做這件事。通常情況下,如果您想在視圖中設置自己的約束,則可以覆蓋UIViews的updateConstraints方法。確保頁面控制器的內容視圖允許調整其邊緣的大小,因爲它們的大小將適合頁面視圖的框架。你的約束和視圖設置將需要考慮到這一點,否則你將得到不可滿足的約束錯誤。

+0

設置框架主要是一個交叉手指的問題,希望它能起作用,儘管知道它是錯誤的。我剛剛嘗試在childviewcontroller的updateViewConstraints中的UIPageViewController視圖和childviewcontroller的根視圖之間設置約束。但仍然沒有骰子。子視圖的大小仍然是0,0; – Rubberduck

+0

當你在這裏創建視圖控制器時:'viewController.view.frame = CGRectMake(self.view.frame.origin.x,self.view.frame.origin.y,self.view.frame.size.width,self。 view.frame.size.height),那個視圖的大小是多少? – gdavis

+0

由於它不起作用,並且由於使用約束條件時我不能做這件事,因此我再也沒有那段代碼。雖然看到我的編輯上面。 – Rubberduck

4

雖然我不知道你正在努力實現視覺上完全什麼,這裏有兩點建議,可以幫助你:

首先,記得在添加新的之前刪除從UIView所有現有的約束碼。不要將Interface Builder中的約束與代碼中的約束混合在一起,它會讓你瘋狂。例如:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    // remove all constraints 
    [self.view removeConstraints:self.view.constraints]; 

    // add new constraints 
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[webView]|" 
                     options:0 
                     metrics:nil 
                     views:@{@"webView": self.webView}]]; 

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[webView]|" 
                     options:0 
                     metrics:nil 
                     views:@{@"webView": self.webView}]]; 
} 

其次,你可以有NSLayoutConstraint網點,就像從廈門國際銀行或一個Storyboard任何其他網點。這樣的話,你可以在運行時調整約束的某些屬性:

// in your header: 
@property (nonatomic, weak) IBOutlet NSLayoutConstraint *myConstraint; 

// somewhere in your code where you need to adjust the constraint: 
self.myConstraint.constant = 100; 

我希望這有助於一點:)

0

我只是碰到了類似的情況。如果我在UIPageViewController的視圖上設置了任何約束,它將與自動調整掩碼約束產生衝突。

對我而言,有效的方法是將UlatesageController視圖的translatesAutoresizingMaskIntoConstraints設置爲NO,然後爲pageController視圖的頂部,左側,寬度和高度的父視圖添加約束。

self.pageController.view.translatesAutoresizingMaskIntoConstraints = NO; 

    NSLayoutConstraint *constraint1 = [NSLayoutConstraint constraintWithItem:self.pageController.view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0]; 
    NSLayoutConstraint *constraint2 = [NSLayoutConstraint constraintWithItem:self.pageController.view attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0.0]; 
    NSLayoutConstraint *constraint3 = [NSLayoutConstraint constraintWithItem:self.pageController.view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeHeight multiplier:1.0 constant:-60.0]; 
    NSLayoutConstraint *constraint4 = [NSLayoutConstraint constraintWithItem:self.pageController.view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0.0]; 

    [self.view addConstraints:@[constraint1, constraint2, constraint3, constraint4]]; 
相關問題