paint-brush
5 Trình bao bọc thuộc tính chính của SwiftUI và cách sử dụng chúng hiệu quảtừ tác giả@tseitlin
3,473 lượt đọc
3,473 lượt đọc

5 Trình bao bọc thuộc tính chính của SwiftUI và cách sử dụng chúng hiệu quả

từ tác giả Mykhailo Tseitlin 9m2023/05/31
Read on Terminal Reader

dài quá đọc không nổi

SwiftUI là một framework để xây dựng giao diện người dùng trên iOS và macOS. Với SwiftUI, bạn có thể mô tả giao diện của mình nên làm gì và trông như thế nào, và framework sẽ lo phần còn lại. SwiftUI có năm trình bao bọc thuộc tính chính: @State, @Binding, @ObserveObject, @StateObject và @EnvironmentObject.
featured image - 5 Trình bao bọc thuộc tính chính của SwiftUI và cách sử dụng chúng hiệu quả
Mykhailo Tseitlin  HackerNoon profile picture
0-item
1-item


Này đó! Tôi muốn nói với bạn về SwiftUI, một framework để xây dựng giao diện người dùng trên iOS và macOS. Nó rất thuận tiện để sử dụng vì nó sử dụng cách tiếp cận khai báo để lập trình. Với SwiftUI, bạn có thể mô tả giao diện của mình nên làm gì và trông như thế nào, và framework sẽ lo phần còn lại.


Một trong những yếu tố chính của SwiftUI là việc sử dụng các trình bao bọc thuộc tính. Đây là những phần tử chức năng cho phép bạn cung cấp logic bổ sung cho các thuộc tính.


SwiftUI có năm trình bao bọc thuộc tính chính:

  1. @Tình trạng

  2. @Binding

  3. @ObserveObject

  4. @StateObject

  5. @EnvironmentObject


Họ sẽ trở thành những người bạn tốt nhất của bạn trong quá trình phát triển.


@Tình trạng


@State cho phép bạn tạo các thuộc tính có thể thay đổi và cập nhật giao diện dựa trên những thay đổi này nếu cần. Ví dụ: nếu bạn muốn tạo một nút thay đổi màu khi được nhấn, bạn có thể tạo một biến @State để lưu màu và thêm màu đó vào nút:


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


@Binding


@Binding cho phép bạn sử dụng một giá trị được lưu trữ trong một phần của mã trong một phần khác của mã. Nó thường được sử dụng trong SwiftUI để chuyển một giá trị từ chế độ xem này sang chế độ xem khác, cho phép chúng tương tác với nhau. Ví dụ: hãy tưởng tượng chúng ta có hai chế độ xem - một chế độ xem có trường văn bản và chế độ xem còn lại có nút. Chúng tôi muốn trường văn bản cập nhật khi người dùng nhấn nút. Để làm điều này, chúng ta có thể sử dụng @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) } }


Trong ví dụ này, @Binding được sử dụng để chuyển giá trị từ $text (trong ContentView ) sang văn bản (trong SecondView ), vì vậy khi người dùng nhấn nút, trường văn bản sẽ cập nhật và hiển thị văn bản mới.


@ObserveObject


@ObserveObject được sử dụng để đánh dấu các thuộc tính được quan sát và có thể thay đổi tùy thuộc vào thay đổi dữ liệu bên ngoài. Trình bao bọc thuộc tính này đăng ký các thay đổi trong đối tượng phù hợp với giao thức ObservableObject và tự động cập nhật các phần có liên quan của giao diện nếu dữ liệu đã thay đổi. Đây là một ví dụ ngắn gọn về việc sử dụng @ObserveObject :

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


Trong ví dụ này, chúng tôi tạo một lớp có tên UserData, lớp này chứa tên @Published. Trong cấu trúc ContentView, chúng tôi tạo một thuộc tính có tên là userData với loại UserData, sử dụng @ObserveObject. Chúng tôi hiển thị giá trị của userData.name trong một trường văn bản và xuất nó trên màn hình.


Khi người dùng thay đổi giá trị trong trường văn bản, SwiftUI sẽ tự động cập nhật phần tương ứng của giao diện, vì thuộc tính name được xuất bản và quan sát bằng cách sử dụng @Published. Điều này có nghĩa là chúng tôi không cần mã riêng để cập nhật giao diện và chúng tôi cho phép SwiftUI làm điều đó cho chúng tôi.


Lưu ý: Nếu bạn chưa biết, @Published là trình bao bọc thuộc tính từ khung Kết hợp có thể được thêm vào thuộc tính lớp hoặc cấu trúc, sẽ tự động gửi thông báo về bất kỳ thay đổi nào đối với giá trị của thuộc tính đó cho bất kỳ ai đã đăng ký thuộc tính đó . Nói cách khác, đó là một thuộc tính trợ giúp cho các thuộc tính có thể được theo dõi để thay đổi.


@StateObject


@StateObject là một trình bao bọc thuộc tính được sử dụng để khởi tạo một đối tượng lớp và lưu trữ nó ở trạng thái xem trong SwiftUI. Điều này có nghĩa là đối tượng được lưu trữ miễn là chế độ xem tồn tại và bị hủy cùng với nó. Thông thường, việc sử dụng @StateObject sẽ thiết thực hơn đối với các đối tượng lớp cần thiết cho nhiều dạng xem chứ không chỉ một dạng xem. Ví dụ:


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


Trong ví dụ này, UserData là một đối tượng của một lớp có chứa một số thuộc tính có thể được sử dụng trong nhiều dạng xem. Lớp này được đánh dấu là ObservableObject để nó có thể được sử dụng với @StateObject@ObserveObject .


Trong ContentView, chúng tôi tạo một đối tượng UserData mới bằng cách sử dụng @StateObject để lưu trạng thái giữa các lần chuyển đổi giữa các chế độ xem khác nhau. Trong trường hợp này, ContentView hiển thị dữ liệu người dùng, trực quan hóa nó và chứa một liên kết đến một dạng xem khác (ProfileView) có thể được sử dụng để chỉnh sửa dữ liệu người dùng.


Trong ProfileView , chúng tôi có quyền truy cập vào cùng một đối tượng UserData bằng cách sử dụng @ObserveObject để sửa đổi dữ liệu người dùng. Khi người dùng thay đổi dữ liệu, nó sẽ tự động được cập nhật trong ContentView vì cùng một đối tượng UserData được sử dụng.


Lưu ý: Sử dụng @ObserveObject nếu bạn cần quan sát các thay đổi trong một đối tượng lớp từ một dạng xem và @StateObject nếu bạn cần lưu trạng thái của một đối tượng lớp ảnh hưởng đến việc hiển thị nhiều dạng xem.


Nếu bạn sử dụng @ObserveObject thay vì @StateObject cho một đối tượng cần thiết trong nhiều dạng xem, thì mỗi dạng xem sẽ có phiên bản đối tượng riêng, điều này có thể dẫn đến sự cố đồng bộ hóa dữ liệu giữa các dạng xem. Do đó, trong trường hợp này, tốt hơn là sử dụng @StateObject.


@EnvironmentObject


@EnvironmentObject là trình bao bọc thuộc tính để xác nhận các đối tượng dữ liệu thông qua hệ thống phân cấp chế độ xem SwiftUI. Nó cho phép truy cập vào đối tượng dữ liệu từ bất kỳ chế độ xem nào trong hệ thống phân cấp SwiftUI thuộc về bộ chứa Môi trường (ví dụ: Cảnh, Chế độ xem, Ứng dụng, v.v.). Ví dụ, hãy tưởng tượng chúng ta có một ứng dụng quản lý danh sách công việc. Chúng ta có thể có một ContentView gốc chứa danh sách các tác vụ và khả năng tạo các tác vụ mới. Đối với điều này, chúng tôi tạo một chế độ xem TaskListView riêng hiển thị danh sách các tác vụ và một nút để thêm các tác vụ mới. Sau khi thêm một tác vụ mới, người dùng sẽ được chuyển hướng đến màn hình thêm tác vụ, vì vậy chúng tôi tạo một chế độ xem AddTaskView riêng.


Để truyền đối tượng UserManager cho cả ba dạng xem, chúng ta có thể tạo thể hiện của nó trong ContentView và sau đó truyền nó dưới dạng tham số cho cả TaskListViewAddTaskView . Tuy nhiên, điều này có thể trở thành vấn đề nếu chúng tôi quyết định thêm nhiều chế độ xem lồng nhau hơn, vì chúng tôi sẽ cần chuyển UserManager qua nhiều chế độ xem trung gian.


Thay vì điều này, chúng ta có thể sử dụng @EnvironmentObject để chuyển UserManager xuống thông qua phân cấp chế độ xem. Bằng cách này, tất cả các chế độ xem cần quyền truy cập vào Trình quản lý người dùng có thể chỉ cần khai báo nó dưới dạng @EnvironmentObject và sử dụng nó khi cần.

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


Vì vậy, bây giờ đối tượng UserManager sẽ tự động được chuyển đến TaskListViewAddTaskView thông qua @EnvironmentObject . Lưu ý rằng chúng tôi có thể sửa đổi trạng thái của Trình quản lý người dùng trong một chế độ xem và các thay đổi sẽ tự động được phản ánh trong chế độ xem khác.



Bài viết đề cập đến các trình bao bọc thuộc tính SwiftUI cơ bản: @State, @Binding, @ObserveObject, @StateObject, @EnvironmentObject.


Các trình bao bọc thuộc tính này tạo thành nền tảng để làm việc với trạng thái ứng dụng trong SwiftUI. Sử dụng bài viết này như một bảng mẹo để có các trình bao bọc thuộc tính cơ bản trong tầm tay của bạn, cần thiết để phát triển ứng dụng với SwiftUI. Bằng cách áp dụng kiến thức này, bạn sẽ có thể xây dựng các giao diện người dùng phức tạp hơn với các trạng thái thay đổi linh hoạt và tích hợp dữ liệu từ các mô hình của bạn vào SwiftUI.