Aula 122: Otimização de Desempenho em SwiftUI
No desenvolvimento de aplicativos modernos, o desempenho é fundamental, especialmente ao lidar com interfaces de usuário complexas. SwiftUI oferece muitos recursos poderosos, mas também requer atenção aos detalhes para manter seu aplicativo funcionando sem problemas. Nesta aula, exploraremos diversas técnicas para otimizar o desempenho de suas aplicações SwiftUI.
1. Use @State
e @Binding
com Sabedoria
SwiftUI utiliza uma sintaxe declarativa e depende fortemente da gestão de estado. Usar @State
e @Binding
de forma excessiva pode levar a re-renderizações desnecessárias das suas views. Certifique-se de usar essas propriedades apenas quando absolutamente necessário.
struct ContentView: View {
@State private var contador = 0
var body: some View {
VStack {
Text("Contagem: \(contador)")
Button("Incrementar") {
contador += 1
}
}
}
}
Neste exemplo, contador
é uma variável de estado simples que permite que a view atualize quando houver mudanças. Garanta que apenas as views que dependem desse estado sejam re-renderizadas.
2. Use @ObservedObject
e @EnvironmentObject
Eficazmente
Para uma gestão de estado mais complexa, você pode usar @ObservedObject
ou @EnvironmentObject
. Isso permite compartilhar dados entre diferentes views sem causar re-renderizações desnecessárias.
class Contador: ObservableObject {
@Published var contador = 0
}
struct ContentView: View {
@ObservedObject var contador = Contador()
var body: some View {
VStack {
Text("Contagem: \(contador.contador)")
Button("Incrementar") {
contador.contador += 1
}
}
}
}
Usando @ObservedObject
, apenas as views que observam esse objeto serão atualizadas quando suas propriedades mudarem.
3. Aproveite a Composição de View
SwiftUI permite criar views complexas ao compor subviews menores. Isso ajuda a isolar o estado e minimiza as re-renderizações.
struct CounterView: View {
@Binding var contador: Int
var body: some View {
VStack {
Text("Contagem: \(contador)")
Button("Incrementar") {
contador += 1
}
}
}
}
struct ContentView: View {
@State private var contador = 0
var body: some View {
CounterView(contador: $contador)
}
}
Neste exemplo, CounterView
é uma view composta que só será atualizada quando contador
mudar, melhorando o desempenho.
4. Minimize o Uso de ForEach
Ao lidar com listas dinâmicas, use ForEach
de forma eficiente. Se possível, evite usá-lo com grandes conjuntos de dados ou quando os dados não mudam com frequência.
struct ContentView: View {
let itens = Array(0..<1000)
var body: some View {
List {
ForEach(itens, id: \.self) { item in
Text("Item \(item)")
}
}
}
}
Considere usar List
com estruturas de dados identificáveis ou comprometa-se com um gerenciamento de lista mais eficiente para minimizar problemas de desempenho.
5. Use Stacks Preguiçosos para Grandes Conjuntos de Dados
Ao exibir grandes conjuntos de dados, considere usar stacks preguiçosos. LazyVStack
e LazyHStack
terão um desempenho melhor porque só criam as views que estão atualmente visíveis.
struct ContentView: View {
let itens = Array(0..<1000)
var body: some View {
ScrollView {
LazyVStack {
ForEach(itens, id: \.self) { item in
Text("Item \(item)")
}
}
}
}
}
Usar LazyVStack
garante que as views só sejam renderizadas quando estão prestes a aparecer na tela.
6. Evite Cálculos Pesados no Corpo
Evite realizar cálculos pesados dentro do corpo das suas views. Em vez disso, compute os valores antes que o corpo seja chamado.
struct ContentView: View {
let dados: [Int] = Array(0..<1000)
var dadosDuplicados: [Int] {
dados.map { $0 * 2 }
}
var body: some View {
List(dadosDuplicados, id: \.self) { item in
Text("Item Duplicado: \(item)")
}
}
}
Ao pré-computar dadosDuplicados
, você pode evitar cálculos pesados durante a renderização da view.
7. Use EquatableView
SwiftUI introduziu EquatableView
para otimizar views que não mudam com frequência. Isso pode reduzir o número de re-renderizações desnecessárias.
struct ItemView: View, Equatable {
let título: String
static func == (lhs: ItemView, rhs: ItemView) -> Bool {
return lhs.título == rhs.título
}
var body: some View {
Text(título)
}
}
struct ContentView: View {
let itens = ["Item 1", "Item 2", "Item 3"]
var body: some View {
ForEach(itens, id: \.self) { item in
EquatableView(content: ItemView(título: item))
}
}
}
Usando EquatableView
, SwiftUI pode evitar a re-renderização para views que não mudaram.
Conclusão
Ao gerenciar cuidadosamente o estado, compor views de forma eficaz e aproveitar as views preguiçosas e os recursos de desempenho do SwiftUI, você pode otimizar significativamente suas aplicações SwiftUI. A otimização de desempenho é um processo contínuo, e estar atento a como suas views reagem às mudanças de estado proporcionará uma experiência mais suave para seus usuários. Boa codificação!