12

特に、UIPageViewController をメイン ビューの子ビューとして設定する必要がある複雑なプロジェクトを構築しています。私は自動レイアウトを使用しており、制約を使用してメイン ビューのさまざまな要素を並べ替えています。

問題は、アプリを実行しようとすると、競合する 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 か月以上コードをいじってみて、今気づいたことです。

まず、pageviewcontroller を設定するビュー コントローラーには、pageviewcontroller を初期化した後、次の 2 行があります。

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

[self.view setTranslatesAutoresizingMaskIntoConstraints:NO];このView Controllerで設定したわけではありません。

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

さて、これは現時点で(私にとっては)機能します。しかし、ハックの少ないソリューションが本当に欲しいです。

4

4 に答える 4

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

NSLayoutConstraint次に、 XIB や 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;

これが少し役立つことを願っています:)

于 2013-12-17T14:15:28.787 に答える
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 は奇妙に見えます。明確に定義されていないように見えます。

于 2013-12-13T17:20:40.453 に答える
1

私はちょうど同様の状況に遭遇しました。UIPageViewController のビューに何らかの制約を設定すると、自動サイズ変更マスクの制約との競合が発生します。

私にとってうまくいくのは、UIPageControllerビューの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]];
于 2014-03-16T00:51:19.460 に答える