2013-10-28 13 views
10

私はUIPageViewControllerをメインビューの子ビューとして設定する必要がある複雑なプロジェクトを構築しています。私はautolayoutを使用しており、制約を使用してメインビューのさまざまな要素を順序付けしています。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を呼び出して)制約を加える方法だと思います。しかし、私は本当にこの問題が解決できる方法を聞いてみたいです。

編集: 私は問題を解決するためのハックを発見しました。私がここにリストアップしているものがソリューション全体であるかどうかはよく分かりませんが、コードで1か月以上の変更をしてから今すぐ気づいています。私は、このビューコントローラに[self.view setTranslatesAutoresizingMaskIntoConstraints:NO];が設定されていることをpageviewcontroller

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

未初期化した後

まず、pageviewcontrollerを設定ビューコントローラでは、私は、次の2行を持っています。

第2に、子コントローラでは、ビューがページビューコントローラの内部または外部で使用されているかどうかを確認します。表示がの場合のみ、012viewerのページビューでが使用されていない場合は、子ビューで[self.view setTranslatesAutoresizingMaskIntoConstraints:NO];が設定されます。

今、これは現時点で(私にとっては)うまくいきます。しかし、私は実際にはそれほどハッキーではない解決策を望んでいます。

+0

クラッシュはおそらく他の原因によるものです。矛盾する制約がある場合、通常、それらの制約の1つを無視します(そして、事実を記録します)。スタックトレース全体を貼り付けることはできますか? –

+0

それは(例を与えることを)言うん:<:0x15671b70のUIView:0x156cf3e0.bottom ==のUIView:0x1568a390.bottom NSLayoutConstraint> objc_exception_throw上 ブレークデバッガでこれをキャッチする は「 が制約を破って回復を試みます にリストされているUIViewのUIConstraintBasedLayoutDebuggingカテゴリのメソッドも役立ちます。 これ以外のログメッセージはありません。そして、このメッセージを与えた後にクラッシュします。 – Rubberduck

+0

あなたは_visually_達成しようとしているものを記述することができますか?それはどんな種類の助言を与えるために非常に便利だろう:) –

答えて

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>" 

は推測では一例で、最後の2 autoresizingmasklayoutconstraintsが私には奇妙に見える、彼らは明確に定義されて見ていません。

+0

私の問題は本当に制約ではありません。私はそれが問題を引き起こしているAutoresizingMaskLayoutConstraintsであることを知っています。問題は、AutoresizingMaskLayoutConstraintを削除する方法は、TranslatesAutoresizingMaskIntoConstraintsをnoに設定することです。私がそれをするとき、UIPageViewControllerにある場合は、ビューをねじ込みます。それが私の問題です。 – Rubberduck

6

AutoLayoutを使用する場合は、ビューのフレームを直接設定しないでください。制約は、これを行うために使用されます。通常、ビュー内に独自の制約を設定する場合は、UIViewのupdateConstraintsメソッドをオーバーライドします。ページコントローラのコンテンツビューでは、ページビューのフレームに合わせてサイズが変更されるため、エッジのサイズを変更できるようにしてください。あなたの制約とビューの設定は、これを考慮する必要があります。そうしないと、満足できない制約エラーが発生します。

+0

フレームを設定することは、主に私の指を横切ることの問題であり、それが間違っていることに気づいてもうまくいくと思っていました。私はちょうどUIPageViewControllerビューとchildviewcontrollerのルートビューの間にchildviewcontrollerのupdateViewConstraintsの制約を設定しようとしました。しかし、ダイスはまだありません。子ビューのサイズはまだ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

私はここで、あなたが視覚的に達成しようとしている内容を正確に把握しませんが、あなたを助けるかもしれないアドバイスの2枚は、以下のとおりです。まず

、新しいものを追加する前に、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}]]; 
} 

第二に、あなただけのXIBやストーリーボードから他店と同様に、NSLayoutConstraint店を持つことができます。そうすれば、あなたは、実行時に制約のある特定の特性を調整することができます。

// 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のビューに制約を設定すると、自動サイズ設定のマスク制約との競合が発生します。

私にとっては、UIPageControllerビューのtranslatesAutoresizingMaskIntoConstraintsをNOに設定してから、pageControllerビューのtop、left、width、およびheightの親ビューに制約を追加することです。

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]]; 
関連する問題