New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update actions #230
Update actions #230
Conversation
uhooi
commented
Mar 28, 2024
•
edited
edited
- データソースやリポジトリのメソッドを非同期にした
- 非同期で実行しやすくするため
- データのリフレッシュを ViewModel の init から、Screen の task で実行するように変更した
- Screen の deinit 時にリフレッシュをキャンセルできるようにするため
- リフレッシュが重い場合に画面が固まるのを防ぐため
@@ -63,6 +67,9 @@ package struct SakatsuListScreen: View { | |||
error: viewModel.uiState.sakatsuListError, | |||
onDismiss: { viewModel.send(.screen(.onErrorAlertDismiss)) } | |||
) | |||
.task { | |||
await viewModel.sendAsync(.screen(.task)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
send(_:)
メソッドは同期処理用なので、非同期用に sendAsync(_:)
メソッドと ○○AsyncAction
を用意しました。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
今回は task のみですが、 ○○AsyncAction
は task 以外にも refreshable などが思いつきます。
@@ -68,8 +73,6 @@ final class SakatsuListViewModel: ObservableObject { | |||
self.uiState = SakatsuListUiState() | |||
self.onSettingsButtonClick = onSettingsButtonClick | |||
self.repository = repository | |||
|
|||
refreshSakatsus() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
リフレッシュ処理を ViewModel の init に書くとキャンセルできないため、task へ移動しました。
@@ -133,16 +138,45 @@ final class SakatsuListViewModel: ObservableObject { | |||
} | |||
} | |||
} | |||
|
|||
nonisolated |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ViewModel 全体に @MainActor
を付けているため、メインアクター外で非同期メソッドを実行するために nonisolated
を付けています。
付けないと処理が重い場合に画面が固まってしまいます。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nonisolated
を付けるより、ViewModel 全体から @MainActor
を外し、必要なプロパティやメソッドのみに @MainActor
を付けるほうがいいでしょうか?
意見募集しています!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
あとリフレッシュ中に画面を固まらせない場合、インジケータを表示したり、ビューを disabled
にしたりしたほうがいいでしょうか?
こちらも意見募集しています!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
非同期メソッドの実装次第ですが、 nonisolated
を付けなくてもメインアクター外で実行できたので消しました…。 c9b45fd
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
リフレッシュ中は特に制御しなくてもよさそうです。
ただ保存時はビューを disabled
にしたほうがいいと感じました。
LokiPackage/Sources/Features/Sakatsu/SakatsuList/SakatsuListViewModel.swift
Outdated
Show resolved
Hide resolved
uiState.sakatsus = sakatsus | ||
} | ||
} catch is CancellationError { | ||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
キャンセルはエラー扱いにしません。
@@ -4,7 +4,7 @@ import LogCore | |||
|
|||
// MARK: UI state | |||
|
|||
struct SakatsuInputUiState { | |||
struct SakatsuInputUiState: Sendable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sakatsu
や SakatsuInputError
が Sendable
に準拠していないのに、 SakatsuInputUiState
が Sendable
に準拠できるのってどういう理由でしたっけ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
○○UiState
を Sendable
に準拠させるのは、メインアクター外からゲットしたいためです。
セットは Task { @MainActor in ... }
内で行えばいいです。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SakatsuとSakatsuInputErrorすべてがSendableプロトコルに準拠しているなら、struct SakatsuInputUiStateをSendableプロトコルに準拠してもコンパイルエラーが起こらないので、SakatsuとSakatsuInputErrorもSendableプロトコルに暗黙的に準拠していると考えられます!Takeshiさんの本参考にさせてもらいました。
https://github.com/SatoTakeshiX/first-step-swift-concurrency/blob/main/try-concurrency.playground/Pages/5-1-sendable.xcplaygroundpage/Contents.swift
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public出ないなら暗黙的に準拠できると書いてありました。
なんでpublicだったら暗黙的に準拠できているかまではわからなかったので、また教えてください!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
それだー! ありがと 🙏
暗黙的に準拠しているなら Sendable
を明示的に付けるのをやめました! c9b45fd
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public
だと暗黙的に準拠しない理由は…わからないw
ライブラリとして提供する場合にわかりづらいからとか、、?
LokiPackage/Sources/Features/Sakatsu/SakatsuList/SakatsuListViewModel.swift
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SakatsuとSakatsuInputErrorもSendableプロトコルに暗黙的に準拠していると考えられます。
@@ -4,7 +4,7 @@ import LogCore | |||
|
|||
// MARK: UI state | |||
|
|||
struct SakatsuInputUiState { | |||
struct SakatsuInputUiState: Sendable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SakatsuとSakatsuInputErrorすべてがSendableプロトコルに準拠しているなら、struct SakatsuInputUiStateをSendableプロトコルに準拠してもコンパイルエラーが起こらないので、SakatsuとSakatsuInputErrorもSendableプロトコルに暗黙的に準拠していると考えられます!Takeshiさんの本参考にさせてもらいました。
https://github.com/SatoTakeshiX/first-step-swift-concurrency/blob/main/try-concurrency.playground/Pages/5-1-sendable.xcplaygroundpage/Contents.swift
@@ -4,7 +4,7 @@ import LogCore | |||
|
|||
// MARK: UI state | |||
|
|||
struct SakatsuInputUiState { | |||
struct SakatsuInputUiState: Sendable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public出ないなら暗黙的に準拠できると書いてありました。
なんでpublicだったら暗黙的に準拠できているかまではわからなかったので、また教えてください!