fix: crash on launch in some rare scenarios (closes #615)
This commit is contained in:
1 parent
6803b0232e
commit
5d4b2b0a40
3 files changed
+34
-23
No files matched your search
@@ -19,7 +19,7 @@ class DebugProfile {
|
||||
("OS architecture", Sysctl.run("hw.machine")),
|
||||
("Locale", Locale.current.debugDescription),
|
||||
("Spaces", String(Spaces.allIdsAndIndexes().count)),
|
||||
("Dark mode", Preferences.getString("AppleInterfaceStyle") ?? "Light"),
|
||||
("Dark mode", defaults.string(forKey: "AppleInterfaceStyle") ?? "Light"),
|
||||
("\"Displays have separate Spaces\"", NSScreen.screensHaveSeparateSpaces ? "checked" : "unchecked"),
|
||||
// hardware
|
||||
("Hardware model", Sysctl.run("hw.model")),
|
||||
|
||||
+26
-15
@@ -151,7 +151,7 @@ class Preferences {
|
||||
defaults.string(forKey: key)
|
||||
}
|
||||
|
||||
static func set(_ key: String, _ value: Any?) {
|
||||
static func set(_ key: String, _ value: String) {
|
||||
defaults.set(value, forKey: key)
|
||||
UserDefaults.cache.removeValue(forKey: key)
|
||||
}
|
||||
@@ -436,39 +436,50 @@ enum CrashPolicyPreference: String, CaseIterable, MacroPreference {
|
||||
}
|
||||
|
||||
extension UserDefaults {
|
||||
static var cache = [String: Any]()
|
||||
static var cache = [String: String]()
|
||||
|
||||
func getFromCacheOrFresh<T>(_ key: String, _ getterFn: () -> T?) -> T {
|
||||
func getFromCacheOrFetchAndCache(_ key: String) -> String {
|
||||
if let c = UserDefaults.cache[key] {
|
||||
return c as! T
|
||||
return c
|
||||
}
|
||||
if let v = getterFn() {
|
||||
UserDefaults.cache[key] = v
|
||||
return v
|
||||
}
|
||||
removeObject(forKey: key)
|
||||
let v = getterFn()!
|
||||
let v = defaults.string(forKey: key)!
|
||||
UserDefaults.cache[key] = v
|
||||
return v
|
||||
}
|
||||
|
||||
func getThenConvertOrReset<T>(_ key: String, _ getterFn: (String) -> T?) -> T {
|
||||
let stringValue = getFromCacheOrFetchAndCache(key)
|
||||
if let v = getterFn(stringValue) {
|
||||
return v
|
||||
}
|
||||
removeObject(forKey: key)
|
||||
UserDefaults.cache.removeValue(forKey: key)
|
||||
let stringValue2 = getFromCacheOrFetchAndCache(key)
|
||||
let v = getterFn(stringValue2)!
|
||||
return v
|
||||
}
|
||||
|
||||
func string(_ key: String) -> String {
|
||||
return getFromCacheOrFresh(key, { string(forKey: key)! })
|
||||
return getFromCacheOrFetchAndCache(key)
|
||||
}
|
||||
|
||||
func int(_ key: String) -> Int {
|
||||
return getFromCacheOrFresh(key, { Int(string(key)) })
|
||||
return getThenConvertOrReset(key, { s in Int(s) })
|
||||
}
|
||||
|
||||
func bool(_ key: String) -> Bool {
|
||||
return getFromCacheOrFresh(key, { Bool(string(key)) })
|
||||
return getThenConvertOrReset(key, { s in Bool(s) })
|
||||
}
|
||||
|
||||
func cgfloat(_ key: String) -> CGFloat {
|
||||
return getFromCacheOrFresh(key, { Int(string(key)).map { CGFloat($0) } })
|
||||
return getThenConvertOrReset(key, { s in Int(s).flatMap { CGFloat($0) } })
|
||||
}
|
||||
|
||||
func double(_ key: String) -> Double {
|
||||
return getThenConvertOrReset(key, { s in Double(s) })
|
||||
}
|
||||
|
||||
func macroPref<A>(_ key: String, _ macroPreferences: [A]) -> A {
|
||||
return getFromCacheOrFresh(key, { macroPreferences[safe: int(key)] })
|
||||
return getThenConvertOrReset(key, { s in Int(s).flatMap { macroPreferences[safe: $0] } })
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ class LabelAndControl: NSObject {
|
||||
static func makeLabelWithCheckbox(_ labelText: String, _ rawName: String, extraAction: ActionClosure? = nil, labelPosition: LabelPosition = .leftWithSeparator) -> [NSView] {
|
||||
let checkbox = NSButton(checkboxWithTitle: labelPosition == .right ? labelText : " ", target: nil, action: nil)
|
||||
checkbox.translatesAutoresizingMaskIntoConstraints = false
|
||||
checkbox.state = (Preferences.getString(rawName)! as NSString).boolValue ? .on : .off
|
||||
checkbox.state = defaults.bool(rawName) ? .on : .off
|
||||
let views = makeLabelWithProvidedControl(labelText, rawName, checkbox, labelPosition: labelPosition, extraAction: extraAction)
|
||||
return views
|
||||
}
|
||||
@@ -30,7 +30,7 @@ class LabelAndControl: NSObject {
|
||||
extraAction?(textArea)
|
||||
}
|
||||
textArea.identifier = NSUserInterfaceItemIdentifier(rawName)
|
||||
textArea.stringValue = Preferences.getString(rawName)!
|
||||
textArea.stringValue = defaults.string(rawName)
|
||||
return [textArea]
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ class LabelAndControl: NSObject {
|
||||
let popUp = NSPopUpButton()
|
||||
popUp.translatesAutoresizingMaskIntoConstraints = false
|
||||
popUp.addItems(withTitles: macroPreferences.map { $0.localizedString })
|
||||
popUp.selectItem(at: Int(Preferences.getString(rawName)!)!)
|
||||
popUp.selectItem(at: defaults.int(rawName))
|
||||
return popUp
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ class LabelAndControl: NSObject {
|
||||
return macroPreferences.map {
|
||||
let button = NSButton(radioButtonWithTitle: $0.localizedString, target: nil, action: nil)
|
||||
button.translatesAutoresizingMaskIntoConstraints = false
|
||||
button.state = Int(Preferences.getString(rawName)!)! == i ? .on : .off
|
||||
button.state = defaults.int(rawName) == i ? .on : .off
|
||||
_ = setupControl(button, rawName, String(i), extraAction: extraAction)
|
||||
i += 1
|
||||
return button
|
||||
@@ -64,12 +64,12 @@ class LabelAndControl: NSObject {
|
||||
}
|
||||
|
||||
static func makeLabelWithSlider(_ labelText: String, _ rawName: String, _ minValue: Double, _ maxValue: Double, _ numberOfTickMarks: Int, _ allowsTickMarkValuesOnly: Bool, _ unitText: String = "", extraAction: ActionClosure? = nil) -> [NSView] {
|
||||
let value = Preferences.getString(rawName)!
|
||||
let suffixText = MeasurementFormatter().string(from: Measurement(value: Double(value)!, unit: Unit(symbol: unitText)))
|
||||
let value = defaults.double(rawName)
|
||||
let suffixText = MeasurementFormatter().string(from: Measurement(value: value, unit: Unit(symbol: unitText)))
|
||||
let slider = NSSlider()
|
||||
slider.minValue = minValue
|
||||
slider.maxValue = maxValue
|
||||
slider.stringValue = value
|
||||
slider.stringValue = String(value)
|
||||
slider.isContinuous = true
|
||||
return makeLabelWithProvidedControl(labelText, rawName, slider, suffixText, extraAction: extraAction)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user