2024/9/17
laprasdrum.icon 家族全員ダウン
/icons/hr.icon
SwiftUI Component以外のデザイン向けにカスタムするのは(できなくはないけど)大変という話。
StateObjectにわたすwrappedValueは @autoclosure 属性であるため、viewModelの初期化ロジックまですべてキャプチャさせないとViewのinitializerが再度実行されたとき副作用を生じる可能性がある(= MovieDetailsViewModelの状態が初期化されるとまずいことがあるなら)
Since we’re only passing our local variable to the initializer of StateObject, it means that the StateObject wrapper won’t be able to manage the code that instantiates the view model itself.
As a result, every time that the initializer of the view is executed, a new view model will be created.
But since the StateObject initializer makes sure to execute the closure only once during the entire lifetime of the view, all these extra view models will never be stored inside the StateObject and instead will be immediately released from memory.
This means that in the best scenario, this code is being wasteful by instantiating view models which will never be used.
And in the worst scenario, if the initializer of the view model has any side effects, these side effects will be executed more than they should, which can lead to very subtle bugs.
So remember: whenever you need to instantiate a StateObject wrapper yourself, make sure that you pass the full initialization code as its argument!
code:Sample.swift
// Before
import SwiftUI
struct MovieDetailsView: View {
@StateObject var viewModel: MovieDetailsViewModel
init(movie: Movie) {
let viewModel = MovieDetailsViewModel(movie: movie)
_viewModel = StateObject(wrappedValue: viewModel)
}
var body: some View {
// ...
}
}
// After
import SwiftUI
struct MovieDetailsView: View {
@StateObject var viewModel: MovieDetailsViewModel
init(movie: Movie) {
_viewModel = StateObject(
wrappedValue: MovieDetailsViewModel(movie: movie)
)
}
var body: some View {
// ...
}
}
Debug buildには不要な設定をTimelineから判断する
ENABLE_MODULE_VERIFIER フレームワーク開発者でないのなら配布以外のデバッグビルドには不要そう。
A quick search under the project’s build settings I see most of the newer modules have the ENABLE_MODULE_VERIFIER setting set to YES. Looking at Xcode’s documentation we can find exactly what this does: >In Xcode version 14.3 or later, enable the module verifier in your Xcode project’s build settings so that you can identify and address problems with your framework module before you distribute it. Some examples of these problems include:
Missing header references in your umbrella header
Using quoted includes instead of angle-bracketed includes
Using @import syntax in your public and private headers
Incorrect target conditionals
Imports inside of extern “C” language linkage specification
Non-modular headers in your umbrella header
References to private headers from public headers
>When you enable the module verifier, it finds module problems in your code and displays errors for them in Xcode’s Issue navigator, just like compiler errors or warnings.
This all sounds good and dandy, especially if you’re distributing a framework, but I clearly don’t want to be doing this in Secrets on every build!
So I disabled it for debug builds.
This tweak brought down the build time from 3.5 minutes to 52 seconds 😮!
And it took me less than 30 minutes to find the issue and fix it… I have certainly waited for builds to finish for much longer than that in the past two years.
あわせてXcodeのBuild timelineもチェックしてみる。