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