Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Ограничить элемент в контроллере представления элементом на панели навигации

Автор вопроса: maddieОтветов: 2

ОБНОВИТЬ:

Панель поиска и сегментированный контроллер, заданные в моем первоначальном вопросе, выглядят так:

Я попытался добавить панель поиска в качестве дочернего контроллера представления контроллера навигации в viewDidLoad из BrowseViewController (который не является контроллером навигации)

[self.navigationController addChildViewController:_searchController];
[self.navigationController.view addSubview:_searchController.searchBar];
_searchController.searchBar.frame = self.navigationController.navigationBar.bounds;
[_searchController didMoveToParentViewController:self.navigationController];

Что делает это:

Все на мой взгляд - сегментированный контроль, таблица - пропали.

ОБНОВЛЕНИЕ. Я попытался ограничить сегментированный элемент управления представлением навигационного контроллера в viewWillLayoutSubviews:

         _segmentedControl.translatesAutoresizingMaskIntoConstraints = NO;
           NSLayoutConstraint *segWidthConst = [NSLayoutConstraint constraintWithItem:_segmentedControl attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:350];

          NSLayoutConstraint *segHeightConst = [NSLayoutConstraint constraintWithItem:_segmentedControl attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:32];

        NSLayoutConstraint *segLeadingConstraint = [NSLayoutConstraint constraintWithItem:_segmentedControl attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.navigationController.view attribute:NSLayoutAttributeLeading multiplier:1.0 constant:self.navigationController.navigationItem.titleView.frame.origin.x];

        NSLayoutConstraint *segVerticalConstraint = [NSLayoutConstraint constraintWithItem:_segmentedControl attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.navigationController.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0];
        [_segmentedControl addConstraints:@[segWidthConst, segHeightConst, segLeadingConstraint, segVerticalConstraint]];

Но я получаю эту ошибку:

US[5469:1553682] [LayoutConstraints] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x604000295810 UISegmentedControl:0x7face152bc90.leading == UILayoutContainerView:0x7face141a600.leading   (inactive)>
    When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView(UIConstraintBasedLayout) _viewHierarchyUnpreparedForConstraint:] to debug.
2018-01-28 22:18:29.402296-0500 Leaflet-US[5469:1553682] *** Assertion failure in -[UISegmentedControl _layoutEngine_didAddLayoutConstraint:roundingAdjustment:mutuallyExclusiveConstraints:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3698.33.6/NSLayoutConstraint_UIKitAdditions.m:734
Impossible to set up layout with view hierarchy unprepared for constraint.
(null)

У меня есть контроллер поиска пользовательского интерфейса, который я создаю и помещаю в свой навигационный контроллер внутри viewDidLoad:

/*set appearance of search controller */
_searchController = [[UISearchController alloc]initWithSearchResultsController:nil];
_searchController.searchBar.delegate = self;
_searchController.searchResultsUpdater = self;
[_searchController.searchBar sizeToFit];
_searchController.dimsBackgroundDuringPresentation = NO;
self.definesPresentationContext = YES;
_searchController.hidesNavigationBarDuringPresentation = NO;
_searchController.searchBar.searchBarStyle = UISearchBarStyleDefault;
[self.navigationController.navigationBar setBarTintColor:[UIColor blackColor]];
self.navigationController.navigationBar.translucent = NO;
self.navigationItem.titleView = self.searchController.searchBar;

У меня также есть сегментированный элемент управления, на мой взгляд. Я хочу выровнять ведущее ограничение сегментированного элемента управления с начальным ограничением панели поиска.

Я пытался сделать это в viewWillLayoutSubviews

_segmentedControl.translatesAutoresizingMaskIntoConstraints = NO;
   NSLayoutConstraint *segWidthConst = [NSLayoutConstraint constraintWithItem:_segmentedControl attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:350];

  NSLayoutConstraint *segHeightConst = [NSLayoutConstraint constraintWithItem:_segmentedControl attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:32];

NSLayoutConstraint *segLeadingConstraint = [NSLayoutConstraint constraintWithItem:_segmentedControl attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:_searchController.searchBar attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0.0];

NSLayoutConstraint *segVerticalConstraint = [NSLayoutConstraint constraintWithItem:_segmentedControl attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view.safeAreaLayoutGuide attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0];
[_segmentedControl addConstraints:@[segWidthConst, segHeightConst, segLeadingConstraint, segVerticalConstraint]];

Однако это привело к сбою приложения:

[LayoutConstraints] The view hierarchy is not prepared for the constraint:
        <NSLayoutConstraint:0x600000486180 UISegmentedControl:0x7fa647e13620.leading == UISearchBar:0x7fa647f258f0.leading   (inactive)>
When added to a view, the constraint's items must be descendants of that view (or the view itself).
This will crash if the constraint needs to be resolved before the view hierarchy is assembled.
Break on -[UIView(UIConstraintBasedLayout) _viewHierarchyUnpreparedForConstraint:] to debug.
2018-01-28 18:21:14.589089-0500 Leaflet-US[3891:804350] *** Assertion failure in
-[UISegmentedControl _layoutEngine_didAddLayoutConstraint:roundingAdjustment:
    mutuallyExclusiveConstraints:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3698.33.6/NSLayoutConstraint_UIKitAdditions.m:734
Impossible to set up layout with view hierarchy unprepared for constraint.

Изучая отладку представления, я увидел, что панель поиска действительно не является потомком моего контроллера представления (в отличие от сегментированного элемента управления).

-UITabBarController
 -UILayoutContainerView
  -UitransitionView
   -UIViewControllerWrapperView
    -UINavigationController
     -UILayoutContainerView
      -UINavigationTransitionView
       -UIViewControllerWrapperView
        -BrowseViewController
         -UIView
          -UISegmentedControl
      -UINavigationBar
       -UIBarBackground
       -UINavigationBarContentView
        -UISearchBar

Как я могу ограничить свой сегментированный элемент управления панелью поиска, если контроллер представления контейнера поиска сам заключен в UINavigationController?

  • Как, по вашему мнению, выглядит иерархия? dudeman 29.01.2018
  • @dudeman спасибо, что указали на это - я добавил это в свой пост maddie 29.01.2018
  • Я пытался ограничить сегментированное управление представлением навигационного контроллера, но получаю Impossible to set up layout with view hierarchy unprepared for constraint maddie 29.01.2018

iosobjective-cuinavigationcontrollerconstraintsuisearchcontroller

Ответы

Ответ 1 · dudeman

Есть несколько вещей, которые вы можете попробовать:

1) Добавьте только segWidthConst и segHeightConst к сегментированному элементу управления; и добавьте два других ограничения в контроллер навигации.

2) Получите кадр _searchController.searchBar по отношению к навигационному контроллеру, а затем прикрепите сегментированный контроллер к представлению навигационного контроллера, используя x кадра в качестве константы.

Ответ 2 · Neal.Marlin

Одна вещь, которую вы должны знать, это то, что вы должны добавить ограничение на ближайшее предковое представление представлений, которые используются для его определения. Таким образом, очевидно, что вы не должны добавлять ведущее ограничение к элементу управления сегментом. И в соответствии с иерархией представлений вы можете попытаться добавить ограничение на UILayoutContainerView UINavigationController, потому что это похоже на ближайшее предковое представление.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы