Programación en Swift y SwiftUI para iOS Developers

Cómo redondear las esquinas en SwiftUI

Si hay algo que grita “Diseño de Apple” a los cuatro vientos, son las esquinas redondeadas. Como iOS Developer, te habrás dado cuenta de que prácticamente ningún elemento en la interfaz de usuario de iOS, macOS o watchOS tiene bordes perfectamente afilados. Desde los iconos de la pantalla de inicio hasta las tarjetas de notificaciones, el suavizado de los bordes es un pilar fundamental de las Human Interface Guidelines (HIG) de Apple.

En la era de UIKit, lograr esto requería interactuar directamente con la capa de la vista (view.layer.cornerRadius) e indicarle que recortara el contenido (clipsToBounds = true). Sin embargo, con la llegada del paradigma declarativo, redondear las esquinas de una vista en SwiftUI se ha convertido en un proceso mucho más fluido y expresivo.

En este extenso tutorial de programación Swift, vamos a explorar a fondo cómo dominar las esquinas redondeadas. No solo veremos el clásico modificador cornerRadius, sino que exploraremos las técnicas modernas recomendadas por Apple en Xcode, el concepto del “Squircle” (esquina continua), cómo redondear esquinas específicas y cómo hacer que todo esto funcione de manera impecable en iOS, macOS y watchOS utilizando SwiftUI.


1. El Enfoque Clásico: El Modificador cornerRadius

Cuando SwiftUI fue introducido, la forma más rápida y directa de redondear las esquinas de una vista en SwiftUI era utilizando el modificador .cornerRadius(_:antialiased:).

Este modificador aplica un radio de curvatura uniforme a las cuatro esquinas de la vista a la que se le aplica. Veamos un ejemplo básico de cómo un iOS Developer crearía una tarjeta de perfil simple:

import SwiftUI

struct SimpleCardView: View {
    var body: some View {
        VStack {
            Image(systemName: "person.crop.circle.fill")
                .resizable()
                .frame(width: 80, height: 80)
                .foregroundColor(.white)
            
            Text("iOS Developer")
                .font(.title2)
                .bold()
                .foregroundColor(.white)
        }
        .padding(40)
        .background(Color.blue)
        // Aplicamos el modificador clásico
        .cornerRadius(20) 
        .shadow(radius: 10)
    }
}

El parámetro opcional antialiased (que por defecto es true) asegura que el borde curvo se dibuje de manera suave, combinando los píxeles del borde con el fondo para evitar el temido efecto de “dientes de sierra” o pixelado.

El Fin de una Era: La Deprecación de cornerRadius

Aunque .cornerRadius es increíblemente fácil de usar, tiene limitaciones estructurales. No permite configurar el estilo de la curva y no es componible si deseas añadir bordes del mismo grosor. Por este motivo, a partir de iOS 17 y macOS 14, Apple ha marcado suavemente este modificador con advertencias de deprecación, animando a la comunidad de Swift a utilizar un enfoque basado en formas (Shapes).


2. La Evolución Moderna: clipShape en la Programación Swift

Para escribir código moderno, escalable y preparado para el futuro en Xcode, la forma correcta de redondear las esquinas de una vista en SwiftUI hoy en día es utilizando el modificador .clipShape() en combinación con la estructura RoundedRectangle.

Esto no solo hace exactamente lo mismo que el modificador antiguo, sino que te otorga un control granular sobre cómo se dibuja la curva.

import SwiftUI

struct ModernCardView: View {
    var body: some View {
        Text("Programación Swift Moderna")
            .font(.headline)
            .foregroundColor(.white)
            .padding(30)
            .background(Color.purple)
            // El enfoque moderno y recomendado
            .clipShape(RoundedRectangle(cornerRadius: 25.0))
    }
}

Al usar clipShape, le estamos diciendo a SwiftUI: “Toma el área de esta vista y recórtala usando exactamente esta forma geométrica”. Como RoundedRectangle es un Shape nativo, el rendimiento está altamente optimizado mediante Core Graphics y Metal.


3. La Magia del Diseño de Apple: Continuous vs Circular

Si eres un iOS Developer detallista, quizás hayas notado que un rectángulo redondeado en CSS (web) no se ve exactamente igual que un icono en la pantalla de inicio de tu iPhone, incluso si ambos tienen el mismo radio de esquina. Esto se debe a un concepto llamado “Continuidad de Curvatura” (Curvature Continuity).

Apple utiliza una forma matemática conocida como “Squircle” (una mezcla entre *square* y *circle*). En lugar de pasar bruscamente de una línea recta a una curva circular (lo que crea un salto visual sutil pero perceptible), el diseño de Apple comienza a curvarse gradualmente.

En SwiftUI, esto se controla mediante el parámetro style del RoundedRectangle. Tienes dos opciones:

  • .circular: El redondeo web clásico.
  • .continuous: El redondeo suave y orgánico característico de los dispositivos Apple.

Veamos cómo implementarlo en Swift:

import SwiftUI

struct SquircleView: View {
    var body: some View {
        HStack(spacing: 20) {
            // Estilo Circular Estándar
            Rectangle()
                .fill(Color.red)
                .frame(width: 150, height: 150)
                .clipShape(
                    RoundedRectangle(cornerRadius: 30, style: .circular)
                )
                .overlay(Text("Circular").foregroundColor(.white))
            
            // Estilo Continuo (Apple Squircle)
            Rectangle()
                .fill(Color.green)
                .frame(width: 150, height: 150)
                .clipShape(
                    RoundedRectangle(cornerRadius: 30, style: .continuous)
                )
                .overlay(Text("Continuous").foregroundColor(.white))
        }
        .padding()
    }
}

Como regla general en tu programación Swift: utiliza siempre .continuous a menos que estés replicando explícitamente un diseño web heredado. Es el estándar de oro en iOS, macOS y watchOS.


4. Redondear Esquinas Específicas: El Reto Clásico

Uno de los mayores dolores de cabeza con el antiguo modificador .cornerRadius era cuando el equipo de diseño pedía redondear solo las esquinas superiores de una tarjeta (muy común en *Bottom Sheets* o modales).

La Solución Moderna (iOS 17, macOS 14, watchOS 10+)

Si estás desarrollando aplicaciones con las últimas versiones del SDK en Xcode, Apple nos ha regalado UnevenRoundedRectangle. Esta nueva forma geométrica te permite especificar el radio de cada esquina individualmente de manera declarativa.

import SwiftUI

struct BottomSheetCardView: View {
    var body: some View {
        VStack {
            Text("Solo Esquinas Superiores")
                .font(.title3)
                .foregroundColor(.white)
                .padding()
            Spacer()
        }
        .frame(height: 200)
        .frame(maxWidth: .infinity)
        .background(Color.orange)
        // Disponible en iOS 17+
        .clipShape(
            UnevenRoundedRectangle(
                topLeadingRadius: 40,
                bottomLeadingRadius: 0,
                bottomTrailingRadius: 0,
                topTrailingRadius: 40,
                style: .continuous
            )
        )
    }
}

La Solución Retrocompatible (Soporte para iOS 15 e inferiores)

Si como iOS Developer debes dar soporte a versiones anteriores del sistema operativo, UnevenRoundedRectangle no compilará. En este caso, debemos crear nuestra propia estructura conformando al protocolo Shape utilizando UIBezierPath bajo el capó (o Path directamente en Swift).

import SwiftUI

// Creamos un Shape personalizado
struct CustomRoundedCorners: Shape {
    var radius: CGFloat = .infinity
    var corners: UIRectCorner = .allCorners

    func path(in rect: CGRect) -> Path {
        let path = UIBezierPath(
            roundedRect: rect,
            byRoundingCorners: corners,
            cornerRadii: CGSize(width: radius, height: radius)
        )
        return Path(path.cgPath)
    }
}

// Vista de ejemplo usando nuestro Shape
struct LegacyBottomSheetView: View {
    var body: some View {
        Text("Compatibilidad Extendida")
            .padding(40)
            .background(Color.teal)
            // Aplicamos nuestro Shape personalizado con clipShape
            .clipShape(
                CustomRoundedCorners(
                    radius: 30,
                    corners: [.topLeft, .topRight]
                )
            )
    }
}

Este patrón de diseño es un excelente ejemplo de programación Swift avanzada, demostrando cómo puedes extender SwiftUI envolviendo APIs de bajo nivel de UIKit para resolver problemas complejos de UI.


5. Bordes y Esquinas Redondeadas: Evitando el Defecto Visual

Un error de novato al redondear las esquinas de una vista en SwiftUI es intentar aplicar un borde (stroke) y un radio de esquina al mismo tiempo sin el orden correcto de modificadores. Si aplicas un .border() a una vista redondeada, el borde seguirá siendo un rectángulo cuadrado que se saldrá de los límites de tu curva.

Para solucionar esto de manera elegante en Xcode, usamos superposiciones (overlay) combinadas con formas (Shapes).

import SwiftUI

struct OutlinedCardView: View {
    var body: some View {
        Text("Tarjeta con Borde Redondeado")
            .padding()
            .background(Color.black)
            .foregroundColor(.white)
            // 1. Recortamos el fondo
            .clipShape(RoundedRectangle(cornerRadius: 15, style: .continuous))
            // 2. Superponemos el borde usando exactamente la misma forma
            .overlay(
                RoundedRectangle(cornerRadius: 15, style: .continuous)
                    .stroke(Color.yellow, lineWidth: 3)
            )
    }
}

Al utilizar RoundedRectangle tanto para el clipShape como para el overlay, garantizamos que el borde exterior calce perfectamente con el recorte del contenido interior, logrando un acabado profesional digno de cualquier iOS Developer experto.


6. ContainerRelativeShape: Magia Multiplataforma para iOS, macOS y watchOS

Cuando desarrollas aplicaciones universales, te encuentras con un problema: el radio de esquina que se ve bien en un iPhone Pro Max de 6.7 pulgadas se ve gigantesco en la diminuta pantalla de un Apple Watch. Además, en iOS, los widgets de la pantalla de inicio cambian su radio de esquina dependiendo del dispositivo físico del usuario.

Para resolver esto, SwiftUI introdujo ContainerRelativeShape. Esta forma especial no toma un radio numérico fijo; en su lugar, le pregunta a su contenedor padre (o al sistema operativo) cuál debería ser su curvatura para mantenerse en armonía con el entorno.

import SwiftUI

struct AdaptiveWidgetView: View {
    var body: some View {
        ZStack {
            // El fondo toma la forma que el sistema considere correcta
            ContainerRelativeShape()
                .fill(Color.indigo)
            
            VStack {
                Text("Widget Adaptativo")
                    .font(.headline)
                    .foregroundColor(.white)
            }
        }
        // Aplicamos un padding relativo
        .padding(16)
    }
}

Esta técnica es obligatoria si estás creando extensiones de Widgets (WidgetKit) en Xcode, ya que garantiza que tu UI respetará las curvas exactas del dispositivo, sin importar si el usuario tiene un iPhone 15 o un iPad Pro, unificando tu programación Swift en todo el ecosistema.


7. Consideraciones de Rendimiento y Sombras

Al redondear las esquinas de una vista en SwiftUI, modificas cómo el motor de renderizado (Core Animation) dibuja los píxeles en pantalla. Si tienes listas enormes (como un LazyVStack o un List) llenas de tarjetas con esquinas redondeadas y sombras, el rendimiento podría degradarse al hacer scroll.

El Problema con clipShape y shadow

Si aplicas un shadow después de un clipShape, SwiftUI calculará la sombra basándose en el contorno exacto del recorte. Esto es computacionalmente costoso.

Mejor práctica para el iOS Developer: Aplica el color de fondo y la forma simultáneamente usando .background() con un Shape, y luego aplica la sombra. Esto es mucho más eficiente que recortar el contenido principal.

import SwiftUI

struct HighPerformanceCard: View {
    var body: some View {
        HStack {
            Image(systemName: "bolt.fill")
                .foregroundColor(.yellow)
            Text("Alta Eficiencia")
                .fontWeight(.medium)
        }
        .padding()
        // En lugar de usar background(Color) + clipShape(), hacemos ambos en un solo paso
        .background(
            RoundedRectangle(cornerRadius: 12, style: .continuous)
                .fill(Color.white)
                // Aplicamos la sombra directamente a la forma
                .shadow(color: .black.opacity(0.15), radius: 5, x: 0, y: 3)
        )
    }
}

Este enfoque le evita a Xcode tener que hacer una pasada de máscara (masking pass) de renderizado fuera de pantalla (off-screen rendering), lo que mantendrá los fotogramas de tu app clavados en los 120fps en dispositivos ProMotion.


Conclusión

Redondear las esquinas de una vista en SwiftUI puede parecer un tema trivial al principio, pero como hemos visto a lo largo de este tutorial de programación Swift, encierra una gran profundidad arquitectónica y de diseño.

Hemos evolucionado desde el simple y depreciado cornerRadius, abrazando el robusto clipShape y los rectángulos irregulares (UnevenRoundedRectangle), hasta comprender la belleza matemática detrás de la curva continua (Squircle) de Apple.

Como iOS Developer, dominar estas sutilezas en Xcode es lo que separa una aplicación que simplemente “funciona” de una que se siente verdaderamente nativa, refinada y digna de estar en el ecosistema de iOS, macOS y watchOS.

Si tienes cualquier duda sobre este artículo, contacta conmigo y estaré encantado de ayudarte 🙂. Puedes contactar conmigo en mi perfil de X o en mi perfil de Instagram

Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Article

ImageRenderer en SwiftUI

Next Article

Cómo crear un botón con una imagen en SwiftUI

Related Posts