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

ОБНОВИТЬ:

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

Я попытался добавить панель поиска в качестве дочернего контроллера представления контроллера навигации в 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?


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


Ответы (2)


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

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

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

person dudeman    schedule 29.01.2018
comment
Я попробовал первый и получил, Impossible to set up layout with view hierarchy unprepared for constraint. Кажется, я не могу попробовать второй, если я не могу успешно ограничить сегментированный элемент управления представлением навигационного контроллера? - person maddie; 29.01.2018
comment
Может быть, попробовать добавить ограничения в viewWillAppear вместо viewDidLoad? - person dudeman; 29.01.2018
comment
На самом деле я добавляю ограничения в viewWillLayoutSubviews, но я могу попробовать viewWillAppear - person maddie; 29.01.2018
comment
Вместо этого я попробовал viewWillAppear и получил тот же сбой - person maddie; 29.01.2018
comment
Я только что заметил одну вещь: вы не добавляете контроллер поиска в качестве дочернего контроллера представления контроллера навигации. Так может попробовать пройти этот процесс? - person dudeman; 29.01.2018
comment
Вместо self.navigationItem.titleView = self.searchController.searchBar; у меня есть [self.navigationController.view addSubview:_searchController.searchBar] (и ограничения в viewWillLayoutSubviews), я получаю тот же сбой - person maddie; 29.01.2018
comment
Я имел в виду нечто большее: developer.apple.com/library/content/featuredarticles/ - person dudeman; 29.01.2018
comment
Похоже, что добавление подвида в контроллер навигации не поддерживается:/ - person maddie; 30.01.2018

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

person Neal.Marlin    schedule 29.01.2018