UISearchBar aumenta la altura de la barra de navegación en iOS 11

89

Tengo mi UISearchBarser parte de la barra de navegación como:

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

Después de actualizar a iOS 11algo extraño sucedió en la barra de búsqueda en mi aplicación. Una iOS 10y otra vez, mi barra de navegación se veía así:

ingrese la descripción de la imagen aquí

Ahora con iOS 11tengo:

ingrese la descripción de la imagen aquí

Como puede ver, hay una diferencia en el redondeo de las dos barras de búsqueda, lo que no me molesta. El problema es que la barra de búsqueda aumenta la altura de la barra de navegación. Entonces, cuando voy a otro controlador, también se ve extraño:

ingrese la descripción de la imagen aquí

De hecho, la altura de la extraña línea negra más la altura de la barra de navegación actual es igual a la altura de la barra de navegación que se muestra en la segunda imagen ...

¿Alguna idea de cómo deshacerse de la línea negra y tener una altura de barra de navegación constante en todos los controladores de vista?

radioaktiv
fuente
Posible duplicado de la
barra de búsqueda

Respuestas:

66

Obtuve una línea negra debajo de NavigationBar con SearchBar en iOS 11 en dos casos:

  • cuando empujé otro ViewControllers de ViewController con UISearchBar ingrese la descripción de la imagen aquí

  • cuando descarté ViewController con UISearchBar con "arrastrar a la derecha para descartar" ingrese la descripción de la imagen aquí

Mi solución fue: agregar este código a mi ViewController con 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
}

Actualización de 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
}
Andrés
fuente
2
Use esto con precaución ya que para mí hizo que toda la aplicación se congelara cuando se intentaba deslizar hacia atrás al controlador de vista anterior
Abd Al-rhman Taher Badary
1
Esta solución realmente me da un gran alivio gracias @andrew
Sagar Daundkar
67

Puede agregar una restricción de altura 44 a la barra de búsqueda para iOS 11.

// Rápido

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

// C objetivo

if (@available(iOS 11.0, *)) {
    [searchBar.heightAnchor constraintEqualToConstant:44].active = YES;
}
zgjie
fuente
12
Aunque esto funciona para devolver la altura a la normalidad, si toco en mi barra de búsqueda, por alguna razón, corta la parte inferior de la barra de búsqueda. ¿Alguna idea de por qué sucede esto o alguien más que tenga este problema?
Christopher Smit
9
Un aspecto totalmente extraño si usa este código porque solo reduce la barra de navegación, pero la altura de la barra de búsqueda sigue siendo 56.
OtakuFitness
4
¿Alguien más encontró una solución? Hacer esto crea muchos problemas de comportamiento extraños con la barra de búsqueda.
Gustavo_fringe
15
Esta no es una respuesta suficiente. Cuando haces clic en el campo, el tamaño aún está desordenado.
Ross
5
Esto no funciona en iOS 13. ¿Alguna solución para esto?
VV
42

Creo que en iOS 11, UISearchBar ahora tiene la altura igual a 56, y UINavigationBar usa el diseño automático para adaptarse a sus subvistas, por lo que aumenta la altura. Si aún desea tener UISearchBar como titleView como en versiones anteriores de iOS 11, descubrí que la mejor manera de hacerlo es incrustar UISearchBar en una vista personalizada, establecer la altura de esta vista en 44 y asignarla 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
fuente
Esto funciona correctamente pero tiene problemas cuando lo cambia a horizontal de vertical.
Malav Soni
Gran solución si no está utilizando el diseño automático. Hasta ahora, esto parece funcionar también para el modo horizontal, en el simulador.
Ryan H.
He publicado una solución que soluciona problemas de cambio de orientación.
de.
Esta respuesta resolvió todos los problemas. La respuesta de zgjie es excelente, pero el marco de la barra de búsqueda aún cambió después de tocar el campo de texto.
Charlie Hung
19

prueba este código en el controlador de vista "ACKNOWLEDGMENTS" en viewDidLoad

self.extendedLayoutIncludesOpaqueBars = true
Viento de plata
fuente
¡Gracias! Esta es la solución con la que terminé optando, ya que no estoy usando barras translúcidas.
mmh02
De hecho, esta debería ser la respuesta. Pero me gustaría agregar que coloque este fragmento de código tanto en el controlador que está encima como debajo del controlador de la barra de búsqueda.
Amrit Sidhu
Eso funcionó para mí, pero tuve que agregar navigationController? .View.layoutSubviews () en viewWillDisappear.
douglasd3
Esto funciona muy bien, le agradecería mucho que nos dijera qué extendedLayoutIncludesOpaqueBars hace la propiedad.
Anirudha Mahale
ExtendedLayoutIncludesOpaqueBars expande su vista (self.view) debajo de la barra de navegación y estado. Si agrega una subvista a la vista (por ejemplo, UIImageView) y establece la restricción en la parte superior izquierda de la vista y ejecuta la aplicación, verá la diferencia cuando establezca esta propiedad entre verdadero y falso.
Silverwind
6

¡Gracias a todos! Finalmente encontré una solución.

Agregar el siguiente código a ViewController con UISearchBar.

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

En Objective-C

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

Esto también me pasó a mí, todo funciona bien en iOS 12.4 y se vuelve extraño en el 13 anterior. El problema está en el aumento de altura de la barra de navegación de iOS 13 de 88 a 100 después de saltar desde UIViewController que implementa searchBar.

Pruebe esto en su UIViewController que implementa searchBar.

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

Vista previa después de corregir:

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

Vista previa antes de corregir:

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

Avendi Sianipar
fuente
1

EDITAR: La respuesta @zgjie es una mejor solución para este problema: https://stackoverflow.com/a/46356265/1713123

Parece que esto sucede porque en iOS 11 el valor de altura predeterminado de SearchBar se cambió a 56, en lugar de 44 en las versiones anteriores de iOS.

Por ahora, he aplicado esta solución, estableciendo la altura de la barra de búsqueda de nuevo en 44:

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

Otra solución podría ser usar la nueva propiedad searchController en navigationItem en iOS 11 :

navigationItem.searchController = searchController

Pero de esta manera, la barra de búsqueda aparece debajo del título de navegación.

alemorgado
fuente
1
¿Está documentado el cambio en alguna parte? No pude encontrarlo aquí .
Iulian Onofrei
1
FYI, puede modificar el marco sin crear una variable para él; CGRect().insetBy(dx:dy:)y CGRect().offsetBy(dx:dy:), en este caso -searchController.searchBar.frame = searchController.searchBar.frame.insetBy(dx: 0, dy: -12)
Oscar Apeland
Esta solución funcionó, pero cuando hace clic en la barra de búsqueda, se restablece la altura.
Gustavo_fringe
@Gustavo_fringe ¿Encontraste alguna solución para esto?
Shivam Pokhriyal
1

Toda la solución no funcionó para mí, así que antes de presionar el controlador de vista, lo hice:

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

    self.navigationItem.titleView = UIView()
}

Y para hacer que la barra de búsqueda esté presente al regresar:

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

    self.navigationItem.titleView = UISearchBar()
}
Mantas Laurinavičius
fuente
Esto eliminó la vista negra en el nuevo controlador de vista, pero al regresar a este controlador de vista (el que contiene searchBar), rootView realmente se movió un poco hacia arriba.
code4latte
1

No pude usar la solución de mantener la barra de navegación en 44. Así que me tomó un día, pero finalmente encontré una solución que no cambia la altura de la barra y coloca el botón en el medio de la barra. El problema es que los botones se colocan en una vista de pila que está configurada como vista de pila horizontal y, por lo tanto, no se ajusta al cambio de altura.

Esto se hace en 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)];
}

en viewWillApear (o en cualquier momento después de que se agregó la vista a la pila de navegación)

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

Y subviewOfClass es una categoría en 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
fuente
1

Todo lo que tiene que hacer es subclase UISearchBar y anular "intrinsicContentSize":

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

ingrese la descripción de la imagen aquí

Jagie
fuente
1

No puedo comentar, pero quería compartir algunos problemas adicionales que encontré mientras pasaba muchas horas tratando de llegar al fondo de este problema, incluso después de usar una de las otras soluciones.

Parece que la mejor solución para mí fue la respuesta 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
}

Sin embargo, al menos en iOS 12.1 , si su UINavigationBar:

  • se ha isTranslucentconfigurado en false, el controlador de vista con la barra de búsqueda parece no ajustar el diseño de la vista cuando se cierra de forma interactiva (el cierre normal a través del botón Atrás parece funcionar).
  • tiene configurada su imagen de fondo setBackgroundImage(UIImage(), for: .default), la animación de transición no funciona correctamente y volverá a su posición después de terminar.

Sin embargo, estas propiedades particulares se configuraron para que la barra de navegación aparezca de cierta manera, por lo que debo hacer algunos ajustes para recuperarla o soportar el comportamiento extraño. Intentaré recordar actualizar lo anterior si me encuentro con algo más o encuentro otras soluciones o diferencias en otras versiones del sistema operativo.

Oh, amigo
fuente
0

En mi caso, la altura de UINavigationBar más grande no fue un problema para mí. Solo necesitaba realinear los elementos de los botones de la barra izquierda y derecha. Esa es la solución que se me ocurrió:

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

Básicamente, buscamos vistas de pila que contengan elementos de botones de barra y luego cambiamos sus valores de restricciones superiores e inferiores. Sí, es un truco sucio y no recomendaré usarlo si puede solucionar su problema de otra manera.

Roman Serga
fuente
Quiero hacer lo mismo que tú, pero esperaré hasta que surja una solución más elegante. Gracias por compartir de todos modos.
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
fuente
0

Descubrí que la solución de Mai Mai es la única realmente utilizable.
Sin embargo, todavía no es perfecto:
al girar el dispositivo, la barra de búsqueda no cambia de tamaño correctamente y permanece en la dimensión más pequeña.

He encontrado una solución para eso. Aquí está mi código en Objective C con las 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

Ahora todavía queda un caso que aún no he descubierto. Para reproducir, haga lo siguiente:
- comience en vertical
- active el campo de búsqueda
- gire a horizontal
- error: la barra no cambia de tamaño

Delaware.
fuente
0

Arreglé esto agregando la restricción a viewDidAppear en el controlador de vista de mapa donde está incrustada la barra de búsqueda

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
fuente
1
Falta la llamada de super.viewDidAppear (animado)
Reconquistador
0

Hola a la gente que usa UISearchControllery luego adjunta su UISearchBaral navigationItem.titleView. He gastado 4-5 horas locas de mi día para resolver esto. Siguiendo el enfoque recomendado por iOS 11+, que está poniendo el searchControllera navigation.searchControllerno es lo correcto para mi caso. La pantalla que tiene este searchController / searchBar tiene un backButton, uno personalizado.

He probado esto en iOS 10, iOS 11 y 12. En diferentes dispositivos. Solo tenía que hacerlo. No puedo volver a casa sin resolver este demonio. Esto es lo más perfecto que pude hacer hoy, dada mi fecha límite ajustada.

Así que solo quiero compartir este arduo trabajo que hice, depende de ti poner todo donde quieras (por ejemplo, variables en tu viewModel). Aquí va:

En mi primera pantalla (digamos la pantalla de inicio, que no tiene este controlador de búsqueda), tengo esto en mi viewDidLoad().

self.extendedLayoutIncludesOpaqueBars = true

En mi segunda pantalla, la que tiene el searchController, tengo esto en mi viewDidAppear.

anular func viewDidAppear (_ animado: 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.
}

y aquí está la declaración de mi 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
}()

Así que espero que esto ayude a alguien algún día.

Glenn Posadas
fuente
-1

Intenté varias cosas para que el tamaño volviera al 44 original, pero luego la barra de búsqueda siempre se ve y se comporta de manera extraña, como estar demasiado estirada, con desplazamiento y y similares.

Encontré una buena solución aquí (a través de otra publicación de stackoverflow): https://github.com/DreamTravelingLight/searchBarDemo

Simplemente derive su viewcontroller del SearchViewController e incluya en su proyecto las clases SearchViewController y WMSearchbar. Funcionó de la caja para mí sin ningún feo if (iOS11) más ... fealdad.

Martin Schultz
fuente
-1

En mi caso, tengo que disminuir la altura del campo de texto 36pt -> 28pt.

ingrese la descripción de la imagen aquí

Así que intenté cambiar la altura del marco, la altura de la capa. Pero las formas no funcionaron.

Finalmente, encontré una solución que es la máscara. Creo que no es una buena forma, pero 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
    }

Puede cambiar las inserciones, si desea cambiar el marco del campo de texto.

Guarida
fuente