UISearchBar увеличивает высоту панели навигации в iOS 11

89

Я UISearchBarявляюсь частью панели навигации, например:

 let searchBar = UISearchBar()
 //some more configuration to the search bar
 .....
 navigationItem.titleView = searchBar

После обновления iOS 11произошло что-то странное с панелью поиска в моем приложении. На iOS 10и до я моя панель навигации выглядит как:

введите описание изображения здесь

Теперь у iOS 11меня есть:

введите описание изображения здесь

Как видите, разница в округлении двух полос поиска меня не беспокоит. Проблема в том, что панель поиска увеличивает высоту панели навигации. Поэтому, когда я перехожу к другому контроллеру, это тоже выглядит странно:

введите описание изображения здесь

Фактически, высота этой странной черной линии плюс высота текущей панели навигации равна высоте панели навигации, показанной на втором рисунке ...

Есть идеи, как избавиться от черной линии и иметь одинаковую высоту панели навигации для всех контроллеров представления?

радиоактив
источник
Возможный дубликат SearchBar iOS 11 в NavigationBar
Jakub Truhlář 01

Ответы:

66

У меня черная линия под панелью навигации с панелью поиска в iOS 11 была в двух случаях:

  • когда я нажал другой ViewController из ViewController с помощью UISearchBar введите описание изображения здесь

  • когда я уволил ViewController с помощью UISearchBar с «перетащите право, чтобы уволить» введите описание изображения здесь

Мое решение было: добавить этот код в мой ViewController с помощью UISearchBar:

-(void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    [self.navigationController.view setNeedsLayout]; // force update layout
    [self.navigationController.view layoutIfNeeded]; // to fix height of the navigation bar
}

Swift 4 Обновление

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    navigationController?.view.setNeedsLayout() // force update layout
    navigationController?.view.layoutIfNeeded() // to fix height of the navigation bar
}
Андрей
источник
2
Используйте это с осторожностью, так как для меня это
привело к
1
Это решение действительно принесло мне большое облегчение, спасибо @andrew
Сагар Даундкар
67

Вы можете добавить ограничение высоты 44 в строку поиска для iOS 11.

// Swift

if #available(iOS 11.0, *) {
    searchBar.heightAnchor.constraint(equalToConstant: 44).isActive = true
}

// Objective-C

if (@available(iOS 11.0, *)) {
    [searchBar.heightAnchor constraintEqualToConstant:44].active = YES;
}
zgjie
источник
12
Хотя это работает для восстановления нормальной высоты, если я нажимаю на панель поиска, по какой-то причине она обрезает нижнюю часть панели поиска. Есть идеи, почему это происходит, или у кого-то еще есть эта проблема?
Кристофер Смит
9
Совершенно странно выглядит, если вы используете этот код, потому что он просто сужает панель навигации, но высота панели поиска по-прежнему 56.
OtakuFitness
4
Кто-нибудь еще нашел решение? это создает множество странных поведенческих проблем с панелью поиска.
Gustavo_fringe
15
Этого ответа недостаточно. Когда вы нажимаете на поле, размер все равно перепутался.
Росс
5
Это не работает в iOS 13. Есть ли способ обойти это?
ВВ
42

Я считаю, что в iOS 11 UISearchBar теперь имеет высоту, равную 56, а UINavigationBar использует автопрокладку, чтобы соответствовать своим подпредставлениям, поэтому он увеличивает высоту. Если вы по-прежнему хотите иметь UISearchBar в качестве titleView, как в предшествующей iOS 11, я обнаружил, что лучший способ сделать это - встроить UISearchBar в настраиваемое представление и установить высоту этого представления на 44 и назначить его для navigationItem.titleView.

class SearchBarContainerView: UIView {  

    let searchBar: UISearchBar  

    init(customSearchBar: UISearchBar) {  
        searchBar = customSearchBar  
        super.init(frame: CGRect.zero)  

        addSubview(searchBar)  
    }

    override convenience init(frame: CGRect) {  
        self.init(customSearchBar: UISearchBar())  
        self.frame = frame  
    }  

    required init?(coder aDecoder: NSCoder) {  
        fatalError("init(coder:) has not been implemented")  
    }  

    override func layoutSubviews() {  
        super.layoutSubviews()  
        searchBar.frame = bounds  
    }  
}  

class MyViewController: UIViewController {  

    func setupNavigationBar() {  
        let searchBar = UISearchBar()  
        let searchBarContainer = SearchBarContainerView(customSearchBar: searchBar)  
        searchBarContainer.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 44)  
        navigationItem.titleView = searchBarContainer  
    }  
} 
Май Май
источник
Это работает правильно, но возникает проблема при изменении его на альбомную ориентацию с портретной.
Малав Сони
Отличное решение, если вы не используете автоматический макет. Пока что это работает и для ландшафтного режима в симуляторе.
Райан Х.
Я опубликовал решение, которое устраняет проблемы с изменением ориентации.
де.
Этот ответ решил все проблемы. Ответ zgjie отличный, но рамка панели поиска все еще изменяется после нажатия на текстовое поле.
Чарли Хунг
19

попробуйте этот код на контроллере представления "ACKNOWLEDGMENTS" в viewDidLoad

self.extendedLayoutIncludesOpaqueBars = true
Silverwind
источник
Благодарность! Это решение, к которому я пришел, поскольку я не использую полупрозрачные полосы.
mmh02 02
На самом деле это должен быть ответ. Но я хотел бы добавить, что поместите этот фрагмент кода в контроллер, который находится над контроллером панели поиска и под ним.
Амрит Сидху
Это сработало для меня, но мне пришлось добавить navigationController? .View.layoutSubviews () в viewWillDisappear.
douglasd3
Это работает очень хорошо, я был бы очень признателен, если бы вы просто рассказали нам, что это за extendedLayoutIncludesOpaqueBars собственность.
Anirudha Mahale
extendedLayoutIncludesOpaqueBars расширяет ваше представление (self.view) под навигационной панелью и строкой состояния. Если вы добавите к представлению подпредставление (например, UIImageView) и установите для него ограничение в верхнем левом углу представления и запустите приложение, вы увидите разницу, если установите для этого свойства значение true и false.
Silverwind
6

Спасибо вам всем! Наконец-то я нашел решение.

Добавление следующего кода в ViewController с помощью UISearchBar.

  1. Первый шаг: viewDidLoad
-(void)viewDidLoad
{
    [super viewDidLoad];
    self.extendedLayoutIncludesOpaqueBars = YES;
    ...
}
override func viewDidLoad() {
    super.viewDidLoad()
    self.extendedLayoutIncludesOpaqueBars = true
}
  1. Второй шаг:viewWillDisappear
-(void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
     // force update layout
    [self.navigationController.view setNeedsLayout]; 
    // to fix height of the navigation bar
    [self.navigationController.view layoutIfNeeded];  
}
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        navigationController?.view.setNeedsLayout() // force update layout
        navigationController?.view.layoutIfNeeded() // to fix height of the navigation bar
    }
BlessNeo
источник
4

В Objective-C

if (@available(iOS 11.0, *)) {
        [self.searchBar.heightAnchor constraintLessThanOrEqualToConstant: 44].active = YES;
}              
Hassy
источник
2

Это случилось и со мной, все работало хорошо в iOS 12.4 и становилось странным в 13 выше. Проблема заключается в увеличении высоты панели навигации iOS 13 с 88 до 100 после перехода из UIViewController, реализующего searchBar.

Попробуйте это в своем UIViewController, который реализует searchBar.

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    navigationController?.view.setNeedsLayout()
    navigationController?.view.layoutIfNeeded()
}

Предварительный просмотр после исправления:

введите описание изображения здесь введите описание изображения здесь

Предварительный просмотр перед исправлением:

введите описание изображения здесь введите описание изображения здесь

Avendi Sianipar
источник
1

РЕДАКТИРОВАТЬ: ответ @zgjie - лучшее решение этой проблемы: https://stackoverflow.com/a/46356265/1713123

Похоже, это происходит потому, что в iOS 11 значение высоты SearchBar по умолчанию было изменено на 56, а не на 44 в предыдущих версиях iOS.

На данный момент я применил этот обходной путь, установив высоту searchBar обратно на 44:

let barFrame = searchController.searchBar.frame
searchController.searchBar.frame = CGRect(x: 0, y: 0, width: barFrame.width, height: 44)    

Другим решением может быть использование нового свойства searchController в navigationItem в iOS 11 :

navigationItem.searchController = searchController

Но так da searchBar появляется под заголовком навигации.

алеморгадо
источник
1
Это изменение где-то задокументировано? Я не мог найти его здесь .
Юлиан
1
К вашему сведению, вы можете изменить фрейм, не создавая для него переменную; CGRect().insetBy(dx:dy:)и CGRect().offsetBy(dx:dy:), в этом случае -searchController.searchBar.frame = searchController.searchBar.frame.insetBy(dx: 0, dy: -12)
Оскар Апеланд
Это решение сработало, но когда вы нажимаете на панель поиска, высота сбрасывается.
Gustavo_fringe
@Gustavo_fringe Вы нашли какое-нибудь решение для этого.
Шивам Похриял 02
1

Все решения у меня не работали, поэтому, прежде чем я нажал на контроллер представления, я сделал:

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    self.navigationItem.titleView = UIView()
}

И чтобы при возвращении отображалась панель поиска:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    self.navigationItem.titleView = UISearchBar()
}
Мантас Лауринавичюс
источник
Это удалило черный вид в новом контроллере просмотра, но при возврате к этому контроллеру просмотра (тот, который содержит searchBar), rootView фактически немного сдвинулся вверх.
code4latte
1

Я не мог использовать решение с сохранением navBar на уровне 44. Так что мне потребовался день, но, наконец, я нашел решение, которое не меняет высоту панели и не помещает кнопку в середину панели. Проблема в том, что кнопки размещаются в виде стека, который настроен как горизонтальный вид стека и поэтому не подстраивается под изменение высоты.

Это делается при инициализации:

UIBarButtonItem *cancelButton;
if (@available(iOS 11.0, *)) {
    // For iOS11 creating custom button to accomadate the change of navbar + search bar being 56 points
    self.navBarCustomButton = [UIButton buttonWithType:UIButtonTypeCustom];
    [self.navBarCustomButton setTitle:@"Cancel"];
    [self.navBarCustomButton addTarget:self action:@selector(cancelButtonTapped) forControlEvents:UIControlEventTouchUpInside];
    cancelButton = [[UIBarButtonItem alloc] initWithCustomView:self.navBarCustomButton];
} else {
    cancelButton = [[UIBarButtonItem alloc] initWithTitle:MagicLocalizedString(@"button.cancel", @"Cancel")
                                                                                         style:UIBarButtonItemStylePlain
                                                                                        target:self
                                                                                        action:@selector(cancelButtonTapped)];
}

на viewWillApear (или в любое время после добавления представления в стек навигации)

   if (@available(iOS 11.0, *)) {
        UIView *buttonsStackView = [navigationController.navigationBar subviewOfClass:[UIStackView class]];
        if (buttonsStackView ) {
            [buttonsStackView.centerYAnchor constraintEqualToAnchor:navigationController.navigationBar.centerYAnchor].active = YES;
            [self.navBarCustomButton.heightAnchor constraintEqualToAnchor:buttonsStackView.heightAnchor];
        }
    }

И subviewOfClass - это категория в UIView:

- (__kindof UIView *)subviewOfClass:(Class)targetClass {
     // base case
     if ([self isKindOfClass:targetClass]) {
        return self;
     }

     // recursive
    for (UIView *subview in self.subviews) {
        UIView *dfsResult = [subview subviewOfClass:targetClass];

        if (dfsResult) {
           return dfsResult;
       }
   }
   return nil;
}
Зеев Вакс
источник
1

Все, что вам нужно сделать, это создать подкласс UISearchBar и переопределить intrinsicContentSize:

@implementation CJSearchBar
-(CGSize)intrinsicContentSize{
    CGSize s = [super intrinsicContentSize];
    s.height = 44;
    return s;
}
@end

введите описание изображения здесь

Джаги
источник
1

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

Похоже, что лучшим решением для меня был ответ Эндрю :

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    navigationController?.view.setNeedsLayout() // force update layout
    navigationController?.view.layoutIfNeeded() // to fix height of the navigation bar
}

Однако, по крайней мере, в iOS 12.1 , если у вас UINavigationBar:

  • уже isTranslucentустановлено false, в View Controller с появляется панель поиска , чтобы не получить макет регулируется подпереть его Высказаться, когда в интерактивном режиме увольнения (нормальный , отказавшие через спину появляется кнопка для работы).
  • если задано фоновое изображение setBackgroundImage(UIImage(), for: .default), анимация перехода не работает должным образом и после завершения вернется на свое место.

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

Ohifriend
источник
0

В моем случае большая высота UINavigationBar для меня не проблема. Мне просто нужно было выровнять элементы левой и правой кнопок панели. Вот решение, которое я придумал:

- (void)iOS11FixNavigationItemsVerticalAlignment
{
    [self.navigationController.navigationBar layoutIfNeeded];

    NSString * currSysVer = [[UIDevice currentDevice] systemVersion];
    if ([currSysVer compare:@"11" options:NSNumericSearch] != NSOrderedAscending)
    {
        UIView * navigationBarContentView;
        for (UIView * subview in [self.navigationController.navigationBar subviews])
        {
            if ([subview isKindOfClass:NSClassFromString(@"_UINavigationBarContentView")])
            {
                navigationBarContentView = subview;
                break;
            }
        }

        if (navigationBarContentView)
        {
            for (UIView * subview in [navigationBarContentView subviews])
            {
                if (![subview isKindOfClass:NSClassFromString(@"_UIButtonBarStackView")]) continue;

                NSLayoutConstraint * topSpaceConstraint;
                NSLayoutConstraint * bottomSpaceConstraint;

                CGFloat topConstraintMultiplier = 1.0f;
                CGFloat bottomConstraintMultiplier = 1.0f;

                for (NSLayoutConstraint * constraint in navigationBarContentView.constraints)
                {
                    if (constraint.firstItem == subview && constraint.firstAttribute == NSLayoutAttributeTop)
                    {
                        topSpaceConstraint = constraint;
                        break;
                    }

                    if (constraint.secondItem == subview && constraint.secondAttribute == NSLayoutAttributeTop)
                    {
                        topConstraintMultiplier = -1.0f;
                        topSpaceConstraint = constraint;
                        break;
                    }
                }

                for (NSLayoutConstraint * constraint in navigationBarContentView.constraints)
                {
                    if (constraint.firstItem == subview && constraint.firstAttribute == NSLayoutAttributeBottom)
                    {
                        bottomSpaceConstraint = constraint;
                        break;
                    }

                    if (constraint.secondItem == subview && constraint.secondAttribute == NSLayoutAttributeBottom)
                    {
                        bottomConstraintMultiplier = -1.0f;
                        bottomSpaceConstraint = constraint;
                        break;
                    }
                }

                CGFloat contentViewHeight = navigationBarContentView.frame.size.height;
                CGFloat subviewHeight = subview.frame.size.height;
                topSpaceConstraint.constant = topConstraintMultiplier * (contentViewHeight - subviewHeight) / 2.0f;
                bottomSpaceConstraint.constant = bottomConstraintMultiplier * (contentViewHeight - subviewHeight) / 2.0f;
            }
        }
    }
}

По сути, мы ищем представления стека, которые содержат элементы кнопок панели, а затем меняем их значения верхних и нижних ограничений. Да, это грязный хакер, и я не рекомендую его использовать, если вы можете решить свою проблему каким-либо другим способом.

Роман Серга
источник
Я хочу сделать то же самое, что и вы, но подожду, пока не появится более элегантное решение. В любом случае спасибо, что поделились.
Майкл Пиротт
0
//
//  Created by Sang Nguyen on 10/23/17.
//  Copyright © 2017 Sang. All rights reserved.
//

import Foundation
import UIKit

class CustomSearchBarView: UISearchBar {
    final let SearchBarHeight: CGFloat = 44
    final let SearchBarPaddingTop: CGFloat = 8
    override open func awakeFromNib() {
        super.awakeFromNib()
        self.setupUI()
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.setupUI()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
       // fatalError("init(coder:) has not been implemented")
    }
    func findTextfield()-> UITextField?{
        for view in self.subviews {
            if view is UITextField {
                return view as? UITextField
            } else {
                for textfield in view.subviews {
                    if textfield is UITextField {
                        return textfield as? UITextField
                    }
                }
            }
        }
        return nil;
    }
    func setupUI(){
        if #available(iOS 11.0, *) {
            self.translatesAutoresizingMaskIntoConstraints = false
            self.heightAnchor.constraint(equalToConstant: SearchBarHeight).isActive = true
        }
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        if #available(iOS 11.0, *) {
            if let textfield = self.findTextfield() {
                textfield.frame = CGRect(x: textfield.frame.origin.x, y: SearchBarPaddingTop, width: textfield.frame.width, height: SearchBarHeight - SearchBarPaddingTop * 2)`enter code here`
                return
            }
        }
    }
}
Sang_longan
источник
0

Я обнаружил, что решение Mai Mai - единственное, что действительно можно использовать.
Однако это все еще не идеально:
при повороте устройства панель поиска не изменяется должным образом и остается в меньшем размере.

Я нашел исправление для этого. Вот мой код в Objective C с аннотациями соответствующих частей:

// improvements in the search bar wrapper
@interface SearchBarWrapper : UIView
@property (nonatomic, strong) UISearchBar *searchBar;
- (instancetype)initWithSearchBar:(UISearchBar *)searchBar;
@end
@implementation SearchBarWrapper
- (instancetype)initWithSearchBar:(UISearchBar *)searchBar {
    // setting width to a large value fixes stretch-on-rotation
    self = [super initWithFrame:CGRectMake(0, 0, 4000, 44)];
    if (self) {
        self.searchBar = searchBar;
        [self addSubview:searchBar];
    }
    return self;
}
- (void)layoutSubviews {
    [super layoutSubviews];
    self.searchBar.frame = self.bounds;
}
// fixes width some cases of resizing while search is active
- (CGSize)sizeThatFits:(CGSize)size {
    return size;
}
@end

// then use it in your VC
@implementation MyViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    self.navigationItem.titleView = [[SearchBarWrapper alloc] initWithSearchBar:self.searchController.searchBar];
}
@end

Остался еще один случай, который я еще не выяснил. Для воспроизведения выполните следующие действия:
- начать в портретной ориентации
- активировать поле поиска
- повернуть в альбомную ориентацию
- ошибка: размер панели не изменяется

де.
источник
0

Я исправил это, добавив ограничение для viewDidAppear на контроллере представления карты, где встроена панель поиска.

public override func viewDidAppear(_ animated: Bool) {
    if #available(iOS 11.0, *) {

        resultSearchController?.searchBar.heightAnchor.constraint(equalToConstant: 44).isActive = true
        // searchBar.heightAnchor.constraint(equalToConstant: 44).isActive = true
    }
}
Акшай
источник
1
Вам не хватает вызова super.viewDidAppear (анимированный)
Реконкистадор
0

Привет тем, кто использует, UISearchControllerа затем прикрепляет его UISearchBarк navigationItem.titleView. Я потратил безумные 4-5 часов в день, чтобы решить эту проблему. После IOS 11+ рекомендуется подход, который является принятие searchControllerна navigation.searchControllerне только для моего случая. Экран с этим searchController / searchBar имеет настраиваемую кнопку backButton.

Я тестировал это в iOS 10, iOS 11 и 12. На разных устройствах. Мне просто пришлось. Я не могу пойти домой, не разгадав этого демона. Это лучшее, что я мог сделать на сегодня, учитывая мои сжатые сроки.

Итак, я просто хочу поделиться этой тяжелой работой, которую я проделал, вам решать, где вы хотите поместить все, где хотите (например, переменные в вашей модели просмотра). Вот оно:

На моем первом экране (скажем, на главном экране, на котором нет этого контроллера поиска) у меня есть это в моем viewDidLoad().

self.extendedLayoutIncludesOpaqueBars = true

На моем втором экране, на котором есть searchController, у меня это в моем viewDidAppear.

переопределить функцию viewDidAppear (_ animated: Bool) {super.viewDidAppear (анимированный)

    let systemMajorVersion = ProcessInfo.processInfo.operatingSystemVersion.majorVersion
    if systemMajorVersion < 12 {
        // Place the search bar in the navigation item's title view.
        self.navigationItem.titleView = self.searchController.searchBar
    }

    if systemMajorVersion >= 11 {

        self.extendedLayoutIncludesOpaqueBars = true

        UIView.animate(withDuration: 0.3) {
            self.navigationController?.navigationBar.setNeedsLayout()
            self.navigationController?.navigationBar.layoutIfNeeded()
        }

        self.tableView.contentInset = UIEdgeInsets(top: -40, left: 0, bottom: 0, right: 0)

        if self.viewHadAppeared {
            self.tableView.contentInset = .zero
        }
    }

    self.viewHadAppeared = true // this is set to false by default.
}

и вот мое объявление searchController:

lazy var searchController: UISearchController = {
    let searchController = UISearchController(searchResultsController: nil)
    searchController.hidesNavigationBarDuringPresentation = false
    searchController.dimsBackgroundDuringPresentation = false
    searchController.searchBar.textField?.backgroundColor = .lalaDarkWhiteColor
    searchController.searchBar.textField?.tintColor = .lalaDarkGray
    searchController.searchBar.backgroundColor = .white
    return searchController
}()

Так что я надеюсь, что это когда-нибудь поможет кому-нибудь.

Гленн Посадас
источник
-1

Я пробовал разные вещи, чтобы вернуть размер к исходному 44, но тогда панель поиска всегда выглядит и ведет себя странно - например, слишком растянута, смещение по оси Y и тому подобное.

Я нашел здесь хорошее решение (через какое-то другое сообщение stackoverflow): https://github.com/DreamTravelingLight/searchBarDemo

Просто извлеките свой viewcontroller из SearchViewController и включите в свой проект классы SearchViewController и WMSearchbar. Сработало для меня из коробки без какого-либо уродливого if (iOS11) else ... уродства.

Мартин Шульц
источник
-1

В моем случае мне нужно уменьшить высоту текстового поля с 36 пунктов до 28 пунктов.

введите описание изображения здесь

Поэтому я попытался изменить высоту кадра, высоту слоя. Но способы не сработали.

Наконец, я нашел решение - маску. Думаю, это не лучший способ, но он работает.

    let textField              = searchBar.value(forKey: "searchField") as? UITextField
    textField?.font            = UIFont.systemFont(ofSize: 14.0, weight: .regular)
    textField?.textColor       = #colorLiteral(red: 0.1960784314, green: 0.1960784314, blue: 0.1960784314, alpha: 1)
    textField?.textAlignment   = .left

    if #available(iOS 11, *) {
        let radius: CGFloat           = 5.0
        let magnifyIconWidth: CGFloat = 16.0
        let inset                     = UIEdgeInsets(top: 4.0, left: 0, bottom: 4.0, right: 0)

        let path = CGMutablePath()
        path.addArc(center: CGPoint(x: searchBar.bounds.size.width - radius - inset.right - magnifyIconWidth, y: inset.top + radius), radius: radius, startAngle: .pi * 3.0/2.0, endAngle: .pi*2.0, clockwise: false)                        // Right top
        path.addArc(center: CGPoint(x: searchBar.bounds.size.width - radius - inset.right - magnifyIconWidth, y: searchBar.bounds.size.height - radius - inset.bottom), radius: radius, startAngle: 0, endAngle: .pi/2.0, clockwise: false)  // Right Bottom
        path.addArc(center: CGPoint(x: inset.left + radius, y: searchBar.bounds.size.height - radius - inset.bottom), radius: radius, startAngle: .pi/2.0, endAngle: .pi, clockwise: false)                                                  // Left Bottom
        path.addArc(center: CGPoint(x: inset.left + radius, y: inset.top + radius),  radius: radius, startAngle: .pi, endAngle: .pi * 3.0/2.0, clockwise: false)                                                                             // Left top

        let maskLayer      = CAShapeLayer()
        maskLayer.path     = path
        maskLayer.fillRule = kCAFillRuleEvenOdd

        textField?.layer.mask = maskLayer
    }

Вы можете изменить вставки, если хотите изменить фрейм textField.

Ден
источник