@Published risks and usage explained with code examples – onlinecode
In this post we will give you information about @Published risks and usage explained with code examples – onlinecode. Hear we will give you detail about @Published risks and usage explained with code examples – onlinecodeAnd how to use it also give you demo for it if it is necessary.
@Published is one of the property wrappers in SwiftUI that allows us to trigger a view redraw whenever changes occur. You can use the wrapper combined with the ObservableObject protocol, but you can also use it within regular classes.
It’s essential to understand how the published property wrapper works since it can easily lead to unexpected behavior because it’s responding to a will set trigger. Let’s dive into what this means by starting with an explanation of how the wrapper works.
What is the @Published Property Wrapper?
You can use the @Published property wrapper just like other property wrappers by marking a property as follows:
final class ArticleViewModel {
@Published
var title: String = "An example title"
}
The wrapper is class constrained, meaning that you can only use it on instances of a class. An error will occur when used inside a struct:
The wrapped value of the @Published property wrapper represents the actual value of the property:
let viewModel = ArticleViewModel()
print(viewModel.title) // Prints: An example title
The projected value results in a publisher which you can use to observe changes:
var cancellable = viewModel.$title.sink(receiveValue: { newTitle in
print("Title changed to (newTitle)")
})
viewModel.title = "@Published explained"
// Prints:
// Title changed to An example title
// Title changed to @Published explained
Note that we’re using the dollar sign to access the projected value. If you’re new to this technique, I encourage you to read my article Property Wrappers in Swift explained with code examples.
The receive value closure emits both when the value changes and when we subscribe for the first time. You can use the sink operator to respond to any published property changes. For example, you could update a label to represent the initial value of the title and any future updates.
The importance of understanding the willSet trigger
Now that we know the basics of the @Published property wrapper, it’s essential to understand better when a change trigger is published. Publishing of changes occurs in the property’s willSet
block, meaning that any subscribers will receive an update before the property is changed.
To better explain this behavior, we can look at the following code example:
var cancellable = viewModel.$title.sink(receiveValue: { newTitle in
print("Title changed to: '(newTitle)'")
print("ViewModel title is: '(viewModel.title)'")
})
viewModel.title = "@Published explained"
// Prints:
// Title changed to: '@Published explained'
// ViewModel title is: 'An example title'
As you can see, the received value correctly represents the new title. However, the reference of the view model property still returns the previous title.
The behavior described above can easily lead to unexpected bugs. A typical example would be to have a generic function to update a label with the new title:
override func viewDidLoad() {
super.viewDidLoad()
cancellable = viewModel.$title.sink(receiveValue: { [weak self] newTitle in
// Update for title changes.
self?.updateTitleLabel()
})
// Initially update the title label.
updateTitleLabel()
}
func updateTitleLabel() {
titleLabel.text = viewModel.title
print("Title label text is now: '(titleLabel.text ?? "empty")'")
}
The updateTitleLabel()
exists to allow updating the title from multiple places by reusing the same code. However, since we’re calling the method from inside the sink operator, we will trigger the method during the willSet
. As demonstrated before, it will represent the previous value instead of the newly published value.
The fix for the above example would always be to use the publisher as the source of truth:
override func viewDidLoad() {
super.viewDidLoad()
cancellable = viewModel.$title.sink(receiveValue: { [weak self] newTitle in
self?.titleLabel.text = newTitle
print("Title label text is now: '(self?.titleLabel.text ?? "empty")'")
})
}
Using the published title value, we’re constantly making sure to represent the latest published title. We also benefit from the initially published value we receive upon subscribing to the title publishers, making sure our title label initially represents the default title value.
Why willSet and not didSet?
A question you might have is why it’s using the willSet and not the didSet trigger. The reason is that SwiftUI needs to perform diffing between the old state and the new state to decide if a new rendering of the view is necessary. For this to happen we need to have a reference of the old state, which is why the willSet is used.
The love of @Published and @ObservableObject
While the above examples demonstrate the use of the @Published property wrapper inside a regular class, it’s more common to see the wrapper inside an observed object:
final class ArticleViewModel: ObservableObject {
@Published
var title: String = "An example title"
}
The ObservableObject
is a special kind of protocol that synthesizes an objectWillChange
publisher that emits when any of its contained @Published properties changes.
We can explain the above behavior using the following code example:
let viewModel = ArticleViewModel()
viewModel.objectWillChange.sink { _ in
print("Articles view model changed!")
}
viewModel.title = "@Published explained"
// Prints:
// Articles view model changed!
SwiftUI uses the objectWillChange
publisher to redraw its views in response to any change. You can learn more about this technique in my article @StateObject vs. @ObservedObject: The differences explained.
Conclusion
You can use the @Published property wrapper to observe property changes inside any class. Any new values will be published from the willSet
method meaning that we won’t get the latest value when accessed directly. The ObservableObject
protocol works closely together with the property wrapper and allows connecting SwiftUI views to any property changes.
If you like to improve your SwiftUI knowledge, even more, check out the SwiftUI category page. Feel free to contact me or tweet me on Twitter if you have any additional tips or feedback.
Thanks!
<!– Disable cross link to Medium
Also published on Medium.
–>
Hope this code and post will helped you for implement @Published risks and usage explained with code examples – onlinecode. if you need any help or any feedback give it in comment section or you have good idea about this post you can give it comment section. Your comment will help us for help you more and improve us. we will give you this type of more interesting post in featured also so, For more interesting post and code Keep reading our blogs