Open Koshub opened 5 years ago
@Koshub thanks for reaching out!
I think it is more UIKit-friendly way. Or not? Short answer - No.
There is major optimization there.
var props: Props = .initial {
didSet { view.setNeedsLayout() }
}
We're using that approach in couple with Redux
architecture, which assumes that every state update should render new props. Because there may be a lot of these
props - we don't want to force screen update, setNeedsLayout
just notifying UIKit that it should redraw view next time. UIKit decides when to do that. That's why such approach likely to be more UIKit-friendly.
@vmalakhovskiy Thank you very much for response. I completely understand your point of view and it is a comfortable way to update UI using this approach in 99% of the cases. Especially with a lots of frequently state updates.
Allowing UIKit to decide when to render props is a good idea but it doesn't cover the case when you have a state update but not props. In this case it will ask to check layout when it is not necessary. And if we are considering described optimization (which is why this all makes some sense) - forcing the layout check even if the props has not been changed will cost some CPU time on main thread.
The next sample on my iPhone will take more than 3% CPU main thread time to force layout engine to check the layout. Although this is the edge case example it clearly displays the optimization trade offs topic we are trying to achieve with view.setNeedsLayout
.
final class ViewController: UIViewController {
@IBOutlet private weak var titleLabel: UILabel?
struct Props: Equatable {
var title = "0"
}
var props = Props() {
didSet {
// updateView(with: props) // 1-2% CPU load on my iPhone
view.setNeedsLayout() // 3-4% CPU load on my iPhone
}
}
private var timer: Timer?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
timer = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true) { _ in
self.props = Props()
}
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
updateView(with: props)
}
private func updateView(with props: Props) {
titleLabel?.text = props.title
}
}
I think one needs to compare props at least so in case they are the same it will not proceed with layout check.
var props = Props() {
didSet {
if oldValue != props {
view.setNeedsLayout()
}
}
}
I hope I do not bother you too much, since we all are trying to find some silver bullets )) Anyway thank you again for sharing your ideas with the community and for this response. Kind regards.
Just saw https://www.youtube.com/watch?v=i3EBlRjXCvY I like it. Efficient reuse of ReactJS patterns (or whatever). I have one question. What if rather then:
do next:
I think it is more UIKit-friendly way. Or not?