O Beagle já possui alguns widgets básicos que podem ser usados para alterar a sua aplicação UI através do backend. No entanto, você pode adicionar novos componentes para fazer as views da sua aplicação fiquem “visíveis” ao Beagle e que possam também ser usadas no backend.
Abaixo temos a definição da classe do componente Box.
import Foundation
import UIKit
class Box: UIView {
// 1 Class parameter.
private var title: String
// 2 Initialization part of the class.
public init(title: String) {
self.title = title
super.init(frame: .zero)
setupView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// 3 Method to add component to hierarchy and pass position.
private func setupView() {
addSubview(label)
label.text = title
label.topAnchor.constraint(equalTo: topAnchor).isActive = true
label.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
label.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
label.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
}
// 4 Component `UILabel` created.
private lazy var label: UILabel = {
let label = UILabel()
label.font = .systemFont(ofSize: 20, weight: .bold)
label.backgroundColor = .red
label.textAlignment = .center
label.textColor = .white
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
}
Agora temos o componente Box
, para trasformar para um componente Beagle temos adotar o protocolo Widget
, que é um protocolo que conforma com Decodable
e é responsável por decodificar as propriedades que seu widget expõem ao backend.
Crie uma struct BoxWidget adotando protocolo Widget
, a interface widget irá adicionar a property de widgetProperties e o método toView.
widgetProperties: A propriedade de aplicar estilo, id e acessibilidade.
toView: Método para retornar a view do componente criado.
Temos a estrutura da struct BoxWidget
com os parâmetros title
e widgetProperties
e o componente Box
criado no método toView
.
import Foundation
import UIKit
import Beagle
struct BoxWidget: Widget {
// Class parameter.
let title: String
var widgetProperties: WidgetProperties
// toView method of interface the widget.
func toView(renderer: BeagleRenderer) -> UIView {
let boxComponent = Box(title: title)
}
}
Temos que criar a parte de inicialização e decodificação do componente, tem duas maneiras possíveis usando o sourcery
gerador de código para a linguagem Swift, ou fazendo manualmente.
Sourcery:
Para usar o Sourcery
pode encontrar nesse link
Manual:
Para fazer manual tem que criar o init e a decodificação dos parametros title
e widgetProperties
da struct BoxWidget
.
O widgetProperties tem sua propria parte decodificação, entao é preciso apenas passar o decoder para o objeto WidgetProperties
.
// Initialization part of the class.
public init(
title: String,
widgetProperties: WidgetProperties = WidgetProperties()
) {
self.title = title
self.widgetProperties = widgetProperties
}
// Enum with parameters for decoding.
enum CodingKeys: String, CodingKey {
case title
}
// Initialization for decoding
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
title = try container.decode(String.self, forKey: .title)
widgetProperties = try WidgetProperties(from: decoder)
}
Para integrar o componente ao beagle é preciso utilizar o sizeThatFits
ou AutoLayoutWrapper
.
AutoLayoutWrapper:
O objeto calcula o tamanho levando em consideração as contraints do componente.
Para isso primeiro é preciso desabilitar o translatesAutoresizingMaskIntoConstraints
da view do componente, e depois adicionar a view do componente dentro do AutoLayoutWrapper
.
yourComponent.translatesAutoresizingMaskIntoConstraints = false
let beagleWrapper = AutoLayoutWrapper(view: yourComponent)
sizeThatFits:
Método para implementar sua lógica de tamanho, usado na classe do componente customizado.
override func sizeThatFits(_ size: CGSize) -> CGSize {
systemLayoutSizeFitting(size)
}
Agora terminando as configurações, vamos usar o AutoLayoutWrapper
do beagle para configurar o tamanho, pois o componente customizado não possue o sizeThatFits
implementado.
boxComponent.translatesAutoresizingMaskIntoConstraints = false
let beagleWrapper = AutoLayoutWrapper(view: boxComponent)
A classe completa do Widget.
import Foundation
import UIKit
import Beagle
struct BoxWidget: Widget {
// Class parameter.
let title: String
var widgetProperties: WidgetProperties
// Initialization part of the class.
public init(
title: String,
widgetProperties: WidgetProperties = WidgetProperties()
) {
self.title = title
self.widgetProperties = widgetProperties
}
// Enum with parameters for decoding.
enum CodingKeys: String, CodingKey {
case title
}
// Initialization for decoding
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
title = try container.decode(String.self, forKey: .title)
widgetProperties = try WidgetProperties(from: decoder)
}
// toView method of interface the widget.
func toView(renderer: BeagleRenderer) -> UIView {
// Native component declaration.
let boxComponent = Box(title: title)
// Setting the beagle wrapper.
boxComponent.translatesAutoresizingMaskIntoConstraints = false
let beagleWrapper = AutoLayoutWrapper(view: boxComponent)
// Returning BeagleWrapper and component.
return beagleWrapper
}
}
É obrigatório registrá-lo no Beagle. Dentro do arquivo de configuração do beagle utilize o dependencies
para registar.
O método register
possui dois construtores, o primeiro passando apenas o component
e segundo recebendo o component
e named
.
component: Passa a classe do componente.
named: Parâmetro para setar o nome do componente. Não é obrigatório passar. Um caso é quando o nome do componente é registrado diferente com que você criou no backend. Ele será usado na deserializações para encontrar seu componente.
Maneiras de Registrar
// 1
dependencies.decoder.register(component: BoxWidget.self)
// 2
dependencies.decoder.register(component: BoxWidget.self, named: "BoxWidgetComponent")
Após registrar o seu componente de customização, você pode usá-lo via server-driven.
Você pode usar o seu componente declarativamente assim como passá-lo por uma instância até o BeagleScreenViewController
ou chamá-lo via método toView()
para apresentar oUIView
que aparece dentro do seu próprio view controller.
let beagleScreenViewController = Beagle.screen(
.declarative(
.init(child:
BoxWidget(title: "Title my box!")
)
)
)
Exemplo renderizado:
Se você usar componentes mais complexos que estejam no UIViews
ou outros componentes não mencionados, o processo seria parecido.
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.