Adaptando su solución comercial existente para SwiftUI. Parte 1

Buen día a todos. Mi nombre es Anna Zharkova, soy un desarrollador móvil líder de Usetech

Acerca de la tecnología SwiftUI, que Apple anunció el año pasado WWDC 2019, se ha dicho mucho. En principio, ya hay suficiente material sobre sus características, lo que está debajo de su capó y cómo usarlo para una interfaz de usuario rápida y hermosa.



Le ofrezco una breve serie de artículos sobre cómo usar este marco en la vida real y en aplicaciones reales, y no en constructores de sándwiches de aguacate. Y para que todo sea serio y maduro, veremos cómo hacer que nuestra aplicación SwiftUI cumpla con los principios de arquitectura limpia y código limpio.

Pero comencemos con lo básico. Esta parte será solo una introducción e información básica. Entonces, si ya está familiarizado con estas características de SwiftUI, continúe con las siguientes partes:
parte 2 (cómo trabajar con bibliotecas prefabricadas en UIKit)
parte 3 (aquí sobre arquitectura)
parte 4 (aquí sobre navegación)

Si aún no se conocen, entonces pase por unos minutos)

Las características principales del desarrollo declarativo en el nuevo marco son una desviación del uso directo de UIViewController, UIView y el reemplazo por estructuras que implementan el protocolo View. Todos los componentes de la parte visual también se describen mediante la sintaxis declarativa y se encuentran dentro de la propiedad del cuerpo principal de cada Vista. La configuración, la estilización y la personalización de los componentes, la navegación entre la vista en pantalla también se configura mediante la sintaxis declarativa.

Por ejemplo, este código describe una vista para una lista de noticias, haciendo clic en el cual se abre una pantalla con una vista de noticias separada:

struct NewsListView: View{
    @State var data: [NewsItemMock]
    
    var body: some View {
        NavigationView{
        List(data) { item in
            NavigationLink(destination:NewsItemView(item:item)) {
            NewsItemRow(data: item)
            }
        }
    }
}

SwiftUI usa ViewBuilder, un diseñador de interfaz declarativo basado en Functional Builder. Este mecanismo apareció en Swift 5.1 y le permite agrupar elementos en una determinada matriz dentro de un bloque de cierre, por ejemplo, un objeto padre. En la diapositiva se presenta un ejemplo de uso de ViewBuilder. Simplemente colocamos los controles de Vista en el orden que necesitamos, por ejemplo, dentro de una Pila vertical u horizontal, sin usar addSubview, y al compilar SwiftUI agrega y agrupa elementos en un contenedor principal más complejo.

Y aquí está el código:


          VStack {
            HStack {
                VStack(alignment: .leading,spacing: 10) {
                    HeaderText(text: data.title ?? "")
                    SubheaderText(text: data.description ?? "")
                    SmallText(text: data.publishedAt?
                                   .formatToString("dd.MM.yyyy") ?? "")
                }
               ThumbImage(withURL: data.urlToImage ?? "")
             }

convertido a un elemento de lista de 3 campos de texto y una imagen:


Aunque SwiftUI niega el concepto de un UIViewController, el punto de entrada a la aplicación es el UIHostingController, en el que se pasa e incrusta la vista mostrada. Es decir, de hecho, la nueva tecnología es un complemento sobre UIKit:


@available(iOS 13.0, tvOS 13.0, *)
open class UIHostingController<Content> : UIViewController where Content : View {

    public var rootView: Content

    public init(rootView: Content)


Por cierto, todos los controles SwiftUI son análogos declarativos de los controles UIKit.

Por ejemplo, VStack, HStack son análogos del UIStackView vertical y horizontal habitual, respectivamente. La lista es UITableView, el texto es UILabel, el botón es UIButton, la imagen es UIImage, etc.

La conexión y configuración de controles se realiza de manera declarativa utilizando los modificadores disponibles. Los elementos se agrupan dentro de los análogos de UIStackView con algunas propiedades predefinidas.

Además de cambiar la forma en que se describe la parte visual, el control del flujo de datos y el mecanismo de reacción de la IU están cambiando. Swift UI es un marco no dependiente de eventos. Aquellos. Ver en él es el resultado de una función de ciertos estados, y no una secuencia de eventos. La acción realizada por el usuario no cambia la IU directamente, no puede cambiar esto o aquello Ver, agregar o quitar controles. Primero, cambian las propiedades o variables de estado que están conectadas a la Vista a través de uno u otro Contenedores de propiedades (contenedores de propiedades).



Los principales contenedores de propiedades utilizados son:

1.Estado - Utilizado para variables locales.


struct NewsItemRow: View {
    @State var title: String
    @State var  description: String
    @State var dateFormatted: String 
    @State var imageUrl: String 
    
    var body: some View {
        VStack {
            HStack {
                VStack(alignment: .leading,spacing: 10) {
                    HeaderText(text: title)
                    SubheaderText(text: description)
                    SmallText(text: dateFormatted)
                }
              ThumbImage(withURL: imageUrl)
            }
         }
     }

2. @Binding - un análogo de débil, usado cuando se pasa una referencia a un valor.

Lo usamos cuando más de una Vista depende de cualquier propiedad. Por ejemplo, si queremos pasar el valor a la Vista original desde la Vista del segundo nivel.


struct FirstView: View {
    @State var isPresented: Bool = true
    
    var body: some View {
        NavigationView {
            NavigationLink(destination:
            SecondView(isPresented: self.$isPresented)) {
                Text("Some")
            }
        }
    }
}

struct SecondView: View {
    @Binding var isPresented: Bool
    
    var body: some View {
        Button("Dismiss") {
            self.$isPresented = false
        }
    }
}

3. @EnvironmentObject - transfiriendo objetos entre la Vista

4. @ObjectBinding, @ObservableObject - usado para rastrear cambios en las propiedades del modelo usando las herramientas de marco Combinar.


class NewsItemModel: ObservableObject,IModel {
   @Published var title: String
   @Published var  description: String
   @Published var dateFormatted: String 
   @Published var imageUrl: String 
}

Hablaremos de él más tarde.

Entonces. Si queremos cambiar nuestra Vista, cambiamos la propiedad, un anuncio con uno de los Contenedores de propiedades. Luego, la Vista declarativa se reconstruye con todos los controles internos.
Cuando cualquiera de las variables de estado cambia, la Vista se reconstruye como un todo.

Considere un pequeño ejemplo. Tenemos algún tipo de pantalla, en la barra de navegación de la cual hay un botón para agregar contenido a favoritos. Para que podamos cambiar la imagen del indicador en este botón, usaremos PropertyWrappers. Por ejemplo, en este caso, cree una variable local y declararla comoEstado:


struct NewsItemView: View {
@State var isFavorite: Bool 
....

Asignaremos el cambio del valor de la propiedad al evento desencadenante que ocurre cuando se presiona el botón:

struct NewsItemView: View{
    @State var isFavorite: Bool 
   
    var body: some View {
    NavigationView {
    VStack {
        Text("Some content")
       }
    }
     .navigationBarItems(trailing: Button(action: {
            self.isFavorite = !self.isFavorite
        }){
            Image(self.isFavorite ? "favorite" : "unfavorite")
           .frame(width: 20, height: 20, alignment: .topTrailing)
        })
   }
        

Por lo tanto, nuestra Vista cambiará:



y, en principio, esto es todo lo básico que necesita saber sobre SwiftUI para comenzar.

¿Pero es esto suficiente para trabajar?

Para crear interfaces de usuario sin complicaciones a partir de controles simples sin estar atado a Xib y guiones gráficos, por completo.

Y por algo más, no.

En primer lugar, no todos los controles tienen análogos en SwiftUI. Esto se aplica tanto a UIKit UISearchView estándar, UICollectionView, y para qué elementos de bibliotecas de terceros.

En segundo lugar, no hay (o casi ninguna, tal vez alguien lo esté haciendo ahora) soluciones de terceros para trabajar con Data Flow SwiftUI.

Por lo tanto, debe adaptar las soluciones existentes para aplicaciones iOS estándar.

Por favor haga clic en el enlace.

All Articles