UISearchBar aumenta a altura da barra de navegação no iOS 11

89

Eu faço UISearchBarparte da barra de navegação como:

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

Depois de atualizar iOS 11algo estranho aconteceu com a barra de pesquisa do meu aplicativo. No dia iOS 10e antes, minha barra de navegação parecia:

insira a descrição da imagem aqui

Agora com iOS 11eu tenho:

insira a descrição da imagem aqui

Como você pode ver, há diferença no arredondamento das duas barras de pesquisa o que não me incomoda. O problema é que a barra de pesquisa aumenta a altura da barra de navegação. Então, quando vou para outro controlador, também parece estranho:

insira a descrição da imagem aqui

Na verdade, aquela estranha altura da linha preta mais a altura da barra de navegação atual é igual à altura da barra de navegação mostrada na segunda imagem ...

Alguma ideia de como se livrar da linha preta e ter a altura da barra de navegação consistente em todos os controladores de visualização?

radioaktiv
fonte
Possível duplicata do iOS 11 SearchBar na NavigationBar
Jakub Truhlář 01 de

Respostas:

66

Obtive linha preta em NavigationBar com SearchBar no iOS 11 em dois casos:

  • quando eu empurrei outro ViewControllers de ViewController com UISearchBar insira a descrição da imagem aqui

  • quando eu descartei o ViewController com UISearchBar com "arrastar para a direita para dispensar" insira a descrição da imagem aqui

Minha solução foi: adicionar este código ao meu ViewController com 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
}

Atualização do 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
}
Andrew
fonte
2
Use isso com cuidado, pois, para mim, todo o aplicativo congelou quando se tentou deslizar de volta para o controlador de visualização anterior
Abd Al-rhman Taher Badary
1
Esta solução realmente me deu um grande alívio, obrigado @andrew
Sagar Daundkar
67

Você pode adicionar uma restrição de altura 44 à barra de pesquisa do iOS 11.

// Rápido

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
fonte
12
Embora isso funcione para trazer a altura de volta ao normal, se eu tocar em minha barra de pesquisa, por algum motivo, ele corta a parte inferior da barra de pesquisa. Alguma ideia de por que isso acontece ou alguém mais tendo esse problema?
Christopher Smit
9
Aparência totalmente estranha se você usar este código porque ele apenas estreita a barra de navegação, mas a altura da barra de pesquisa ainda é 56.
OtakuFitness
4
Alguém mais encontrou uma solução? fazer isso cria muitos problemas comportamentais estranhos com a barra de pesquisa.
Gustavo_fringe
15
Esta não é uma resposta suficiente. Quando você clica no campo, o tamanho ainda está bagunçado.
Ross
5
Isso não funciona no iOS 13. Alguma solução alternativa para isso?
VV
42

Eu acredito que no iOS 11 UISearchBar agora tem altura igual a 56, e UINavigationBar usa autolayout para ajustar suas subvisualizações, portanto, aumenta a altura. Se você ainda deseja ter UISearchBar como titleView como no pré-iOS 11, descobri que a melhor maneira de fazer isso é incorporar UISearchBar em uma visualização personalizada e definir a altura dessa visualização para 44 e atribuí-la a 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  
    }  
} 
Mai Mai
fonte
Isso funciona corretamente, mas tem problemas quando você muda para paisagem de retrato.
Malav Soni
Ótima solução se você não estiver usando o layout automático. Até agora, isso parece funcionar para o modo paisagem também, no simulador.
Ryan H.
Publiquei uma solução que corrige problemas de mudança de orientação.
de.
Esta resposta resolveu todos os problemas. A resposta de zgjie é ótima, mas o quadro da barra de pesquisa ainda mudou após tocar no campo de texto.
Charlie Hung
19

tente este código no controlador de visualização "ACKNOWLEDGMENTS" em viewDidLoad

self.extendedLayoutIncludesOpaqueBars = true
Silverwind
fonte
Obrigado! Essa é a solução que acabei escolhendo, já que não estou usando barras translúcidas.
mmh02
Na verdade, esta deve ser a resposta. Mas gostaria de adicionar que coloque este pedaço de código no controlador acima e abaixo do controlador da barra de pesquisa.
Amrit Sidhu
Isso funcionou para mim, mas tive que adicionar navigationController? .View.layoutSubviews () em viewWillDisappear.
douglasd3
Isso funciona muito bem, eu realmente apreciaria se você apenas nos dissesse o que a extendedLayoutIncludesOpaqueBars propriedade faz.
Anirudha Mahale
extendedLayoutIncludesOpaqueBars expanda sua visualização (self.view) sob a barra de navegação e status. Se você adicionar uma subvisualização à visão (por exemplo, UIImageView) e definir a restrição para o canto superior esquerdo da visão e executar o aplicativo, verá a diferença quando definir essa propriedade entre verdadeiro e falso.
Silverwind
6

Obrigado a todos! Finalmente encontrei uma solução.

Adicionando o seguinte código ao ViewController com UISearchBar.

  1. Primeiro passo: viewDidLoad
-(void)viewDidLoad
{
    [super viewDidLoad];
    self.extendedLayoutIncludesOpaqueBars = YES;
    ...
}
override func viewDidLoad() {
    super.viewDidLoad()
    self.extendedLayoutIncludesOpaqueBars = true
}
  1. Segundo passo: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
fonte
4

Em Objective-C

if (@available(iOS 11.0, *)) {
        [self.searchBar.heightAnchor constraintLessThanOrEqualToConstant: 44].active = YES;
}              
Hassy
fonte
2

Isso aconteceu comigo também, tudo funcionando bem no iOS 12.4 e ficando estranho no 13 acima. O problema está no aumento da altura da barra de navegação do iOS 13 de 88 para 100 após o salto de UIViewController que implementa searchBar.

Tente isso em seu UIViewController que implementa searchBar.

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

Visualização após correção:

insira a descrição da imagem aqui insira a descrição da imagem aqui

Visualize antes de corrigir:

insira a descrição da imagem aqui insira a descrição da imagem aqui

Avendi Sianipar
fonte
1

EDITAR: a resposta @zgjie é a melhor solução para este problema: https://stackoverflow.com/a/46356265/1713123

Parece que isso acontece porque no iOS 11 o valor de altura padrão de SearchBar foi alterado para 56, em vez de 44 nas versões anteriores do iOS.

Por enquanto, apliquei esta solução alternativa, definindo a altura de searchBar de volta para 44:

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

Outra solução poderia ser usar a nova propriedade searchController em navigationItem no iOS 11 :

navigationItem.searchController = searchController

Mas desta forma, a searchBar aparece abaixo do título de navegação.

alemorgado
fonte
1
A mudança está documentada em algum lugar? Não consegui encontrar aqui .
Iulian Onofrei
1
Para sua informação, você pode modificar o quadro sem criar uma variável para ele; CGRect().insetBy(dx:dy:)e CGRect().offsetBy(dx:dy:), neste caso -searchController.searchBar.frame = searchController.searchBar.frame.insetBy(dx: 0, dy: -12)
Oscar Apeland
Esta solução funcionou, mas quando você clica na barra de pesquisa, a altura é redefinida.
Gustavo_fringe
@Gustavo_fringe Você encontrou alguma solução para isso.
Shivam Pokhriyal
1

Todas as soluções não funcionaram para mim, então antes de empurrar o controlador de visualização, eu fiz:

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

    self.navigationItem.titleView = UIView()
}

E para tornar a barra de pesquisa presente ao voltar:

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

    self.navigationItem.titleView = UISearchBar()
}
Mantas Laurinavičius
fonte
Isso removeu a visão preta no novo viewcontroller, mas ao retornar a este viewcontroller (aquele que contém searchBar), o rootView na verdade subiu um pouco.
code4latte
1

Não consegui usar a solução de manter o navBar em 44. Então demorei um dia, mas finalmente encontrei uma solução que não muda a altura da barra e posiciona o botão no meio dela. O problema é que os botões são colocados em uma visualização de pilha configurada como visualização de pilha horizontal e, portanto, não se ajusta à mudança de altura.

Isso é feito no init:

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

em viewWillApear (ou a qualquer momento depois que a visualização foi adicionada à pilha de navegação)

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

E subviewOfClass é uma categoria no 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;
}
Zeev Vax
fonte
1

Tudo que você precisa fazer é criar uma subclasse de UISearchBar e substituir "intrinsicContentSize":

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

insira a descrição da imagem aqui

Jagie
fonte
1

Não é possível comentar, mas gostaria de compartilhar alguns problemas adicionais que encontrei enquanto passava muitas horas tentando chegar ao fundo desse problema, mesmo depois de usar uma das outras soluções.

Parece que a melhor solução para mim foi a resposta de Andrew :

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

No entanto, pelo menos no iOS 12.1 , se UINavigationBar:

  • foi isTranslucentdefinido como false, o View Controller com a barra de pesquisa parece não ter seu layout de view ajustado de volta ao dispensar interativamente (dispensar normal por meio do botão Voltar parece funcionar).
  • tem sua imagem de fundo definida usando setBackgroundImage(UIImage(), for: .default), a animação de transição não funciona corretamente e voltará para sua posição após terminar.

Essas propriedades específicas foram definidas para fazer a barra de navegação aparecer de uma certa maneira, no entanto, eu preciso fazer alguns ajustes para recuperá-la ou aguentar o comportamento estranho. Tentarei me lembrar de atualizar o acima, se encontrar algo diferente ou encontrar outras soluções ou diferenças em outras versões do sistema operacional.

Ohifriend
fonte
0

No meu caso, a altura maior do UINavigationBar não foi um problema para mim. Eu só precisava realinhar os itens dos botões da barra esquerda e direita. Essa é a solução que eu encontrei:

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

Basicamente, procuramos por visões de pilha que contêm itens de botão de barra e, em seguida, alteramos seus valores de restrição superior e inferior. Sim, é um hack sujo e não recomendo usá-lo se você puder consertar seu problema de qualquer outra maneira.

Roman Serga
fonte
Quero fazer a mesma coisa que você, mas vou esperar até que surja uma solução mais elegante. Obrigado por compartilhar de qualquer maneira.
Michael Pirotte
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
fonte
0

Eu descobri que a solução de Mai Mai é a única realmente utilizável.
No entanto, ainda não é perfeito:
ao girar o dispositivo, a barra de pesquisa não é redimensionada corretamente e permanece em uma dimensão menor.

Eu encontrei uma solução para isso. Aqui está meu código em Objective C com as partes relevantes anotadas:

// 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

Agora ainda há um caso que eu não descobri ainda. Para reproduzir, faça o seguinte:
- comece em retrato
- ative o campo de pesquisa
- gire para paisagem
- erro: a barra não redimensiona

de.
fonte
0

Corrigi isso adicionando a restrição para viewDidAppear no controlador de visualização de mapa onde a barra de pesquisa está embutida

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
    }
}
Akshay
fonte
1
Você está perdendo a chamada de super.viewDidAppear (animado)
Reconquistador,
0

Olá para as pessoas que usam UISearchControllere, em seguida, anexando-as UISearchBarao navigationItem.titleView. Eu gastei 4-5 horas loucas do meu dia para resolver isso. Após o iOS 11+ abordagem recomendada, que é colocar o searchControllerà navigation.searchControllernão é apenas adequado para o meu caso. A tela que tem esse searchController / searchBar tem um backButton, customizado.

Eu testei isso no iOS 10, iOS 11 e 12. Em diferentes dispositivos. Eu apenas tive que fazer. Não posso ir para casa sem resolver esse demônio. Isso é o mais perfeito que eu poderia fazer hoje, devido ao meu prazo apertado.

Então, eu só quero compartilhar este trabalho árduo que fiz, cabe a você colocar tudo onde quiser (ex. Variáveis ​​em seu viewModel). Aqui vai:

Na minha primeira tela (digamos tela inicial, que não tem esse controlador de pesquisa), tenho isso na minha viewDidLoad().

self.extendedLayoutIncludesOpaqueBars = true

Na minha segunda tela, aquela que contém o searchController, tenho isso na minha viewDidAppear.

substituir função viewDidAppear (_ animated: Bool) {super.viewDidAppear (animado)

    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.
}

e aqui está a declaração de meu 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
}()

Espero que algum dia isso ajude alguém.

Glenn
fonte
-1

Tentei várias coisas para voltar ao tamanho original 44, mas a barra de pesquisa sempre parece e se comporta de forma estranha - como estar muito esticada, com deslocamento em y e semelhantes.

Encontrei uma boa solução aqui (por meio de alguma outra postagem stackoverflow): https://github.com/DreamTravelingLight/searchBarDemo

Basta derivar seu viewcontroller do SearchViewController e incluir em seu projeto as classes SearchViewController e WMSearchbar. Funcionou fora da caixa para mim, sem qualquer feio if (iOS11) ... feio.

Martin Schultz
fonte
-1

No meu caso, tenho que diminuir a altura do textField 36pt -> 28pt.

insira a descrição da imagem aqui

Então tentei mudar a altura da moldura, a altura da camada. Mas os caminhos não funcionaram.

Finalmente, encontrei uma solução que é a máscara. Eu penso: não é uma boa maneira, mas funciona.

    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
    }

Você pode alterar as inserções, se quiser alterar a moldura do textField.

Den
fonte