[Features] Fixes potential crash when handling .settingsDidChange Notification

Handling .settingsDidChange notification in the same run loop as changing an @Option’s value can result in exclusive memory access violation due to accessing Option.settingsKey. As a workaround, we delay posting the notification until a later run loop via Task.
This commit is contained in:
Riley Testut 2023-04-25 15:14:16 -05:00
parent 77b26210ab
commit 7ad5df1949

View File

@ -59,14 +59,16 @@ public class Option<Value: OptionValue, DetailView: View>: _AnyOption
}
}
set {
Task { @MainActor in
// Delay to avoid "Publishing changes from within view updates is not allowed" runtime warning.
(self.feature?.objectWillChange as? ObservableObjectPublisher)?.send()
}
do {
try UserDefaults.standard.setOptionValue(newValue, forKey: self.settingsKey.rawValue)
NotificationCenter.default.post(name: .settingsDidChange, object: nil, userInfo: [SettingsUserInfoKey.name: self.settingsKey, SettingsUserInfoKey.value: newValue])
Task { @MainActor in
// Delay to avoid "Publishing changes from within view updates is not allowed" runtime warning.
(self.feature?.objectWillChange as? ObservableObjectPublisher)?.send()
// Delay to avoid potential simultaneous memory access runtime error.
NotificationCenter.default.post(name: .settingsDidChange, object: nil, userInfo: [SettingsUserInfoKey.name: self.settingsKey, SettingsUserInfoKey.value: newValue])
}
}
catch {
print("[ALTLog] Failed to set option value for key \(self.settingsKey.rawValue).", error)