From 7ad5df1949a0a5af68d4496c9309298cba9ba736 Mon Sep 17 00:00:00 2001 From: Riley Testut Date: Tue, 25 Apr 2023 15:14:16 -0500 Subject: [PATCH] [Features] Fixes potential crash when handling .settingsDidChange Notification MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- DeltaFeatures/Option.swift | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/DeltaFeatures/Option.swift b/DeltaFeatures/Option.swift index d261c9a..7723bf1 100644 --- a/DeltaFeatures/Option.swift +++ b/DeltaFeatures/Option.swift @@ -59,14 +59,16 @@ public class Option: _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)