paint-brush
Os 5 principais wrappers de propriedade do SwiftUI e como usá-los efetivamentepor@tseitlin
3,473 leituras
3,473 leituras

Os 5 principais wrappers de propriedade do SwiftUI e como usá-los efetivamente

por Mykhailo Tseitlin 9m2023/05/31
Read on Terminal Reader

Muito longo; Para ler

SwiftUI é uma estrutura para criar interfaces de usuário no iOS e macOS. Com o SwiftUI, você pode descrever o que sua interface deve fazer e se parecer, e a estrutura cuidará do resto. SwiftUI tem cinco wrappers de propriedades principais: @State, @Binding, @ObservedObject, @StateObject e @EnvironmentObject.
featured image - Os 5 principais wrappers de propriedade do SwiftUI e como usá-los efetivamente
Mykhailo Tseitlin  HackerNoon profile picture
0-item
1-item


Ei! Gostaria de falar sobre o SwiftUI, uma estrutura para criar interfaces de usuário no iOS e macOS. É muito conveniente de usar porque emprega uma abordagem declarativa para programação. Com o SwiftUI, você pode descrever o que sua interface deve fazer e se parecer, e a estrutura cuidará do resto.


Um dos principais elementos do SwiftUI é o uso de wrappers de propriedade. Esses são elementos funcionais que permitem fornecer lógica adicional para propriedades.


SwiftUI tem cinco wrappers de propriedade principais:

  1. @Estado

  2. @Vinculativo

  3. @ObservedObject

  4. @StateObject

  5. @EnvironmentObject


Eles se tornarão seus melhores amigos no desenvolvimento.


@Estado


@State permite criar propriedades que podem ser alteradas e, se necessário, atualizar a interface com base nessas alterações. Por exemplo, se você deseja criar um botão que muda de cor quando pressionado, você pode criar uma variável @State para armazenar a cor e adicioná-la ao botão:


 struct MyButton: View { @State var buttonColor = Color.blue var body: some View { Button("Press me!") { buttonColor = Color.red } .background(buttonColor) } }


@Vinculativo


@Binding permite que você use um valor armazenado em uma parte do código em outra parte do código. Normalmente é usado no SwiftUI para passar um valor de uma visualização para outra, permitindo que elas interajam umas com as outras. Por exemplo, imagine que temos duas visualizações - uma com um campo de texto e outra com um botão. Queremos que o campo de texto seja atualizado quando o usuário pressiona o botão. Para fazer isso, podemos usar @Binding:


 struct ContentView: View { @State private var text = "" var body: some View { VStack { TextField("Enter text", text: $text) Button("Update text") { text = "New text" } SecondView(text: $text) } } } struct SecondView: View { @Binding var text: String var body: some View { Text(text) } }


Neste exemplo, @Binding é usado para passar o valor de $text (que está em ContentView ) para text (que está em SecondView ), então quando o usuário pressionar o botão, o campo de texto será atualizado e exibirá o novo texto.


@ObservedObject


@ObservedObject é usado para marcar as propriedades que são observadas e podem mudar dependendo das mudanças de dados externos. Este wrapper de propriedade se inscreve nas alterações no objeto que está em conformidade com o protocolo ObservableObject e atualiza automaticamente as partes relevantes da interface se os dados forem alterados. Aqui está um breve exemplo de uso de @ObservedObject :

 class UserData: ObservableObject { @Published var name = "John" } struct ContentView: View { @ObservedObject var userData = UserData() var body: some View { VStack { Text("Hello, \(userData.name)!") TextField("Enter your name", text: $userData.name) } } }


Neste exemplo, criamos uma classe chamada UserData, que contém um nome @Published. Na estrutura ContentView, criamos uma propriedade chamada userData com o tipo UserData, utilizando @ObservedObject. Exibimos o valor de userData.name em um campo de texto e o exibimos na tela.


Quando o usuário altera o valor no campo de texto, o SwiftUI atualiza automaticamente a parte correspondente da interface, pois a propriedade name é publicada e observada usando @Published. Isso significa que não precisamos de nosso próprio código para atualizar a interface e permitimos que o SwiftUI faça isso por nós.


Nota: Se você não sabe, @Published é um wrapper de propriedade do framework Combine que pode ser adicionado a uma propriedade de classe ou estrutura, que envia automaticamente notificações de qualquer alteração no valor dessa propriedade para qualquer pessoa que a tenha assinado . Em outras palavras, é um atributo auxiliar para propriedades que podem ser rastreadas quanto a alterações.


@StateObject


@StateObject é um wrapper de propriedade usado para inicializar um objeto de classe e armazená-lo no estado de exibição em SwiftUI. Isso significa que o objeto é armazenado enquanto a exibição existir e é destruído junto com ele. Normalmente, usar @StateObject é mais prático para objetos de classe necessários para várias exibições, não apenas uma. Por exemplo:


 class UserData: ObservableObject { @Published var name = "John" @Published var age = 30 } struct ContentView: View { @StateObject var userData = UserData() var body: some View { NavigationView { VStack { Text("Name: \(userData.name)") Text("Age: \(userData.age)") NavigationLink( destination: ProfileView(userData: userData), label: { Text("Edit Profile") }) } .navigationTitle("Home") } } } struct ProfileView: View { @ObservedObject var userData: UserData var body: some View { Form { TextField("Name", text: $userData.name) Stepper("Age: \(userData.age)", value: $userData.age) } .navigationTitle("Profile") } }


Neste exemplo, UserData é um objeto de uma classe que contém várias propriedades que podem ser usadas em várias exibições. A classe é marcada como ObservableObject para que possa ser usada com @StateObject e @ObservedObject .


Em ContentView, criamos um novo objeto UserData usando @StateObject para salvar o estado entre as transições entre diferentes exibições. Nesse caso, ContentView exibe os dados do usuário, os visualiza e contém um link para outra exibição (ProfileView) que pode ser usado para editar os dados do usuário.


Em ProfileView , obtemos acesso ao mesmo objeto UserData usando @ObservedObject para modificar os dados do usuário. Quando o usuário altera os dados, eles são atualizados automaticamente no ContentView porque o mesmo objeto UserData é usado.


Observação: use @ObservedObject se precisar observar alterações em um objeto de classe a partir de uma exibição e @StateObject se precisar salvar o estado de um objeto de classe que afeta a exibição de várias exibições.


Se você usar @ObservedObject em vez de @StateObject para um objeto necessário em várias exibições, cada exibição terá sua própria instância do objeto, o que pode levar a problemas com a sincronização de dados entre as exibições. Portanto, neste caso, é melhor usar @StateObject.


@EnvironmentObject


@EnvironmentObject é um wrapper de propriedade para passar objetos de dados pela hierarquia de exibição do SwiftUI. Ele permite o acesso ao objeto de dados a partir de qualquer visualização na hierarquia SwiftUI que pertença ao container Ambiente (por exemplo, Cena, Visualização, Aplicativo, etc.). Por exemplo, imagine que temos um aplicativo de gerenciamento de lista de tarefas. Podemos ter um ContentView raiz que contém uma lista de tarefas e a capacidade de criar novas tarefas. Para isso, criamos uma visualização TaskListView separada que exibe a lista de tarefas e um botão para adicionar novas tarefas. Depois de adicionar uma nova tarefa, o usuário deve ser redirecionado para a tela de adição de tarefas, então criamos uma exibição AddTaskView separada.


Para passar o objeto UserManager para todas as três exibições, podemos criar sua instância em ContentView e passá-lo como um parâmetro para TaskListView e AddTaskView . No entanto, isso pode se tornar um problema se decidirmos adicionar ainda mais exibições aninhadas, pois precisaremos passar o UserManager por várias exibições intermediárias.


Em vez disso, podemos usar @EnvironmentObject para passar UserManager para baixo na hierarquia de exibição. Dessa forma, todas as visualizações que precisam acessar o UserManager podem simplesmente declará-lo como um @EnvironmentObject e usá-lo conforme necessário.

 struct TaskManagerApp: App { @StateObject var userManager = UserManager() var body: some Scene { WindowGroup { ContentView() .environmentObject(userManager) } } } struct ContentView: View { var body: some View { NavigationView { TaskListView() } } } struct TaskListView: View { @EnvironmentObject var userManager: UserManager var body: some View { List(userManager.tasks) { task in TaskRow(task: task) } .navigationBarTitle("Tasks") .navigationBarItems(trailing: Button(action: { // Navigate to AddTaskView }) { Image(systemName: "plus") } ) } } struct AddTaskView: View { @EnvironmentObject var userManager: UserManager var body: some View { // Add new task using userManager } }


Portanto, agora o objeto UserManager será passado automaticamente para TaskListView e AddTaskView via @EnvironmentObject . Observe que podemos modificar o estado de UserManager em uma visualização e as alterações serão refletidas automaticamente na outra visualização.



O artigo abordou os wrappers básicos de propriedade SwiftUI: @State, @Binding, @ObservedObject, @StateObject, @EnvironmentObject.


Esses wrappers de propriedade formam a base do trabalho com o estado do aplicativo no SwiftUI. Use este artigo como uma folha de dicas para ter os wrappers de propriedade básicos ao seu alcance, necessários para desenvolver aplicativos com SwiftUI. Ao aplicar esse conhecimento, você poderá criar interfaces de usuário mais complexas com estados que mudam dinamicamente e integrar dados de seus modelos no SwiftUI.