Using AutoLayout programmatically for search bar and UITableView

I have a container view that is nearly the full screen sans the status bar.

I then created a UISearchController and a UITableView. I am using ios 9 and doing things programmatically. The bug I am having is when the search bar is touched, the scope options open beneath it but the tableview doesn’t slide down correctly. How do I fix this?

  • EXC_BAD_ACCESS using iCloud on multiple devices
  • Adding Margin to UITableViewCell
  • How to compare SSL certificates using AFNetworking
  • Prevent Core Data From Combining Entities into One Table
  • Getting Exception: “Impossible to set up layout with view hierarchy unprepared for constraint”
  • iPhone 7 Plus - AVFoundation dual camera
  • The code in my viewDidLoad is:

    // Search controller
    self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
    self.searchController.searchResultsUpdater = self;
    self.searchController.dimsBackgroundDuringPresentation = NO;
    self.searchController.searchBar.scopeButtonTitles = @[@"A", @"B", @"C"];
    self.searchController.searchBar.delegate = self;
    [self.searchController.searchBar setTranslatesAutoresizingMaskIntoConstraints:NO];
    
    // UITableView
    self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
    self.tableView.translatesAutoresizingMaskIntoConstraints = NO;
    
    // Container view is defined as the whole screen except 20 points at the top where the status bar is
    [containerView addSubview:self.searchController.searchBar];
    [containerView addSubview:self.tableView];
    
    // The constraints - something is probably wrong here?
    
    // Search bar constraints
    NSDictionary *views2 = @{@"searchBar": self.searchController.searchBar};
    [containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[searchBar]|" options:0 metrics:nil views:views2]];
    [containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[searchBar]|" options:0 metrics:nil views:views2]];
    
    // Tableview constraints
    NSDictionary *views = @{@"tableView": self.tableView};
    [containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[tableView]|" options:0 metrics:nil views:views]];
    [containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[tableView]|" options:0 metrics:nil views:views]];
    

    I need to make the search bar scope options and table view slide properly together. How is this done programmatically?

    3 Solutions Collect From Internet About “Using AutoLayout programmatically for search bar and UITableView”

    You want to attach the top of the UITableView to the bottom of the top layout guide.

    That top layout guide is only available to you when using a Storyboard.

    One more reason to use Interface Builder.


    Reason number 1 = you wouldn’t have this bug in the first place, you would be able to visualize your constraints, and you could achieve all this with exactly 0 lines of code.

    I’m absolutely certain that with the right amount of effort, and support from the SO Community, you can do everything in code. I just find that IB saves not only design time, but offloads debugging to the OS, and ensures longer lifespan to any app. Storyboard allows you to concentrate on what makes your app different from my app, instead of agonizing over layout glitches.

    You can add not only the top layout guide constraint from Interface Builder (Storyboard/xib) but also by programmatically.

    Have you ever try KVConstraintExtensionsMaster library to apply constraints that I have implemented. using this library you can add the top and bottom layout guide constraints Programmatically and many more that are not possible or very difficult from storyboard or xib.

    Put the below code in the viewDidLoad is:

        // create containerView
        containerView = [UIView prepareNewViewForAutoLayout];
        [containerView setBackgroundColor:[UIColor brownColor]];
        [self.view addSubview:containerView];
    
        // create Search controller
        self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
        self.searchController.searchResultsUpdater = self;
        self.searchController.dimsBackgroundDuringPresentation = NO;
        self.searchController.searchBar.delegate = self;
        self.searchController.searchBar.scopeButtonTitles = @[@"A", @"B", @"C"];
    
        // create UITableView
        self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
        [_tableView setBackgroundColor:[UIColor blueColor]];
    
        [self.tableView prepareViewForAutoLayout];
    
        [containerView addSubview:self.searchController.searchBar];
        [containerView addSubview:self.tableView];
    
        // now applying the constraints by using KVConstraintExtensionsMaster library
        // adding leading and trailing contraints of containerView
        [containerView applyLeadingAndTrailingPinConstraintToSuperviewWithPadding:defualtConstant];
    
        // adding Top and Bottom Layout Guidecontraint of containerView
        [self applyTopLayoutGuideConastrainToView:containerView withPadding:defualtConstant];
        [self applyBottomLayoutGuideConastrainToView:containerView withPadding:defualtConstant];
    
        // adding Top constraint of searchBar
        [self.searchController.searchBar applyTopPinConstraintToSuperviewWithPadding:defualtConstant];
    
        // adding leading and trailing contraints of searchBar
        [self.searchController.searchBar applyLeadingAndTrailingPinConstraintToSuperviewWithPadding:defualtConstant];
    
        // adding leading and trailing contraints of tableView
        [self.tableView applyLeadingAndTrailingPinConstraintToSuperviewWithPadding:defualtConstant];
    
        // adding Bottom constraint of tableView
        [self.tableView applyBottomPinConstraintToSuperviewWithPadding:defualtConstant];
    
        // adding vertical constraint between two Sibling views
        // to increase the vertical space between searchBar & tableView, update the spacing value like 10.0 or what you want  
        [self.searchController.searchBar applyConstraintFromSiblingViewAttribute:NSLayoutAttributeBottom toAttribute:NSLayoutAttributeTop ofView:self.tableView spacing:defualtConstant];
    

    Well the constraints are definitely wrong

    They should be like this:

    NSDictionary *views = @{@"tableView": self.tableView,@"searchBar": self.searchController.searchBar};
    
    [containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[searchBar]|" options:0 metrics:nil views:views]];
    [containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[tableView]|" options:0 metrics:nil views:views]];
    [containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[searchBar(44)][tableView]|" options:0 metrics:nil views:views]];
    

    First of all, as you see, you don’t need to create a separate dictionary with the views, but you can use one (more simple IMHO)

    Second the constraints are as follows:

    1. @"H:|[searchBar]|" –> The searchbar is pinned to the left & right of the containerView with the system default (8px) margin
    2. @"H:|[tableView]|" –> The tableView is pinned to the left & right of the containerView with the system default (8px) margin
    3. @"V:|[searchBar(44)][tableView]|" –>

      • The searchbar is pinned to the top of the containerView with the default margin and has a fixed height of 44 pixels
      • The tableView top is pinned to the bottom of the searchBar without any margin
      • The bottom of the tableView is pinned to the bottom of the containerView