場合SwiftUIのView
結合のObservableObject
場合、ビューは自動的にリロードされる任意に関わらず変化が直接ビューに影響を与えるかどうかに-変化が観察物体内で起こります。
これは、重要なアプリのパフォーマンスに大きな問題を引き起こすようです。この簡単な例を参照してください。
// Our observed model
class User: ObservableObject {
@Published var name = "Bob"
@Published var imageResource = "IMAGE_RESOURCE"
}
// Name view
struct NameView: View {
@EnvironmentObject var user: User
var body: some View {
print("Redrawing name")
return TextField("Name", text: $user.name)
}
}
// Image view - elsewhere in the app
struct ImageView: View {
@EnvironmentObject var user: User
var body: some View {
print("Redrawing image")
return Image(user.imageResource)
}
}
ここでは、アプリのさまざまな部分にある2つの無関係なビューがあります。どちらもUser
、環境によって提供される共有への変更を監視します。TextFieldを介しての名前NameView
を編集できますUser
。ImageView
ユーザーのプロフィール画像を表示します。
問題:内部の各キーストロークでNameView
、これを監視するすべてのビューUser
は、ボディコンテンツ全体をリロードすることを余儀なくされます。これにはImageView
、大きな画像のダウンロードやサイズ変更など、費用のかかる操作が含まれる場合があります。
これは、上記の例で簡単に証明できます。これは、TextFieldに新しい文字を入力するたびに"Redrawing name"
と"Redrawing image"
がログに記録されるためです。
質問:ビューの不必要な再描画を回避するために、Observable / Environmentオブジェクトの使用をどのように改善できますか?データモデルを構造化するためのより良い方法はありますか?
これが問題になる理由をわかりやすく説明するためにImageView
、静止画像を表示するだけではないとします。たとえば、次のようになります。
init
またはonAppear
メソッドによってトリガーされた画像を非同期的にロードする他にもたくさんの例がありますが、これらは私の現在のプロジェクトで遭遇したものです。これらの各ケースで、ビューbody
が再計算されると、破棄された状態になり、一部のコストのかかる操作がキャンセル/再開されます。
これがSwiftUIの「バグ」であるとは言えませんが、アプリを設計するためのより良い方法があれば、Appleやチュートリアルで言及されているのを見たことがありません。ほとんどの例は、副作用に対処せずに、EnvironmentObjectの自由な使用を支持しているようです。
なぜオブジェクトImageView
全体が必要なのUser
ですか?
回答:そうではありません。
必要なものだけを取るように変更します。
struct ImageView: View {
var imageName: String
var body: some View {
print("Redrawing image")
return Image(imageName)
}
}
struct ContentView: View {
@EnvironmentObject var user: User
var body: some View {
VStack {
NameView()
ImageView(imageName: user.imageResource)
}
}
}
キーボードのキーをタップすると出力されます。
Redrawing name
Redrawing image
Redrawing name
Redrawing name
Redrawing name
Redrawing name
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加