Adaptando sua solução comercial existente para o SwiftUI. Parte 1

Bom Dia a todos. Meu nome é Anna Zharkova, sou uma desenvolvedora móvel líder da Usetech.

Sobre a tecnologia SwiftUI, anunciada pela Apple no ano passado WWDC 2019, muito foi dito. Em princípio, já existe material suficiente sobre seus recursos, o que há sob o capô e como usá-lo para uma interface de usuário rápida e bonita.



Ofereço uma curta série de artigos sobre como usar essa estrutura na vida real e em aplicações reais, e não em construtores de sanduíche de abacate. E para tornar tudo sério e maduro, veremos como fazer com que nosso aplicativo SwiftUI esteja em conformidade com os princípios de arquitetura e código limpos.

Mas vamos começar com o básico. Esta parte será apenas uma introdução e informações básicas. Portanto, se você já está familiarizado com esses recursos do SwiftUI, vá para as seguintes partes:
parte 2 (como trabalhar com bibliotecas prontas no UIKit)
parte 3 (aqui sobre arquitetura)
parte 4 (aqui sobre navegação)

Se você ainda não se conhece, continue lendo alguns minutos)

Os principais recursos do desenvolvimento declarativo na nova estrutura são um afastamento do uso direto do UIViewController, UIView e substituição por estruturas que implementam o protocolo View. Todos os componentes da parte visual também são descritos usando sintaxe declarativa e estão localizados dentro da propriedade do corpo principal de cada Visualização. Configurações, estilização e customização de componentes, a navegação entre o modo de exibição na tela também é definida usando a sintaxe declarativa.

Por exemplo, este código descreve uma exibição para uma lista de notícias, clicando no qual uma tela é aberta com uma exibição de notícias 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)
            }
        }
    }
}

O SwiftUI usa o ViewBuilder, um designer de interface declarativo baseado no Functional Builder. Esse mecanismo apareceu no Swift 5.1 e permite agrupar elementos em uma determinada matriz dentro de um bloco de fechamento, por exemplo, um objeto pai. Um exemplo do uso do ViewBuilder é apresentado no slide. Simplesmente colocamos os controles View na ordem em que precisamos, por exemplo, dentro de uma pilha vertical ou horizontal, sem usar addSubview, e ao compilar o SwiftUI, ele próprio adiciona e agrupa elementos em um contêiner pai mais complexo.

E aqui está o 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 em um item da lista de 3 campos de texto e uma imagem:


Embora o SwiftUI negue o conceito de um UIViewController, o ponto de entrada para o aplicativo é o UIHostingController, no qual a exibição exibida é passada e incorporada. Na verdade, a nova tecnologia é um complemento do UIKit:


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

    public var rootView: Content

    public init(rootView: Content)


A propósito, todos os controles SwiftUI são análogos declarativos dos controles UIKit.

Por exemplo, VStack, HStack são análogos do UIStackView vertical e horizontal usual, respectivamente. A lista é UITableView, o texto é UILabel, o botão é UIButton, a imagem é UIImage etc.

A conexão e a configuração dos controles são feitas de forma declarativa, usando os modificadores disponíveis. Os elementos são agrupados dentro dos análogos do UIStackView com algumas propriedades predefinidas.

Além de alterar a maneira como a parte visual é descrita, o controle do fluxo de dados e o mecanismo de reação da interface do usuário estão mudando. A interface do usuário Swift é uma estrutura não dependente de evento. Essa. A visão é o resultado de uma função de certos estados, e não de uma sequência de eventos. A ação executada pelo usuário não altera a interface do usuário diretamente, não é possível alterar diretamente essa ou aquela exibição, adicionar ou remover controles. Primeiro, as propriedades ou variáveis ​​de estado conectadas à View por meio de um ou outro Wrapper de propriedade (wrapper de propriedade) são alteradas .



Os principais Wrappers de propriedades usados ​​são:

1.Estado - usado para variáveis ​​locais.


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 - um análogo de fraco, usado ao passar uma referência a um valor.

Usamos quando mais de uma visualização depende de qualquer propriedade. Por exemplo, se queremos passar o valor para a visualização original a partir da visualização do segundo nível.


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 - transferindo objetos entre o View

4. @ObjectBinding, @ObservableObject - usado para rastrear alterações nas propriedades do modelo usando as ferramentas da estrutura Combine.


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

Falaremos sobre ele mais tarde.

Assim. Se quisermos mudar nossa Visualização, alteramos a propriedade, um anúncio com um dos Wrappers de propriedades. Em seguida, a exibição declarativa é reconstruída com todos os controles internos.
Quando qualquer uma das variáveis ​​de estado muda, a Visualização é reconstruída como um todo.

Considere um pequeno exemplo. Temos algum tipo de tela, na barra de navegação, onde existe um botão para adicionar conteúdo aos favoritos. Para alterar a imagem do indicador nesse botão, usaremos o PropertyWrappers. Por exemplo, nesse caso, crie uma variável local e declare-a comoEstado:


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

Atribuiremos a alteração do valor da propriedade ao evento acionador que ocorre quando o botão é pressionado:

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

Assim, nossa Visão mudará:



e, em princípio, estas são todas as coisas básicas que você precisa saber sobre o SwiftUI para começar.

Mas isso é suficiente para funcionar?

Para criar interfaces de usuário descomplicadas a partir de controles simples sem estar vinculado ao Xib e storyboards, completamente.

E para algo mais, não.

Em primeiro lugar, nem todos os controles têm análogos no SwiftUI. Isso se aplica ao UIKit UISearchView, UICollectionView padrão e aos elementos de bibliotecas de terceiros.

Em segundo lugar, não há (ou quase nenhuma, talvez alguém esteja fazendo isso agora) soluções de terceiros para trabalhar com o Data Flow SwiftUI.

Portanto, você precisa adaptar as soluções existentes para aplicativos iOS padrão.

Por favor, clique no link.

All Articles