This crash happens on iOS 15 later only,how can I find the real reason?
My code:
Crash log:
This crash happens on iOS 15 later only,how can I find the real reason?
My code:
Crash log:
It's good to post screenshot but you should also post as code text, that's easier to handle.
Note: you could rewrite the test as
let newTrace = (trace != nil && !trace!.isEmpty) ? trace! : "0"
setValue(forKey:)
is a key-value coding (KVC) method. You should be using the UserDefaults
specific method, namely set(forKey:)
. I don’t think that’ll fix this problem, but it’s the right thing to do regardless.
Also, the screen shot you posted doesn’t align with the crash report. The former indicates a force unwrap issue whereas the latter shows a crash deep within UserDefaults
. Are you chasing two issues? If not, why this disparity?
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Does anyone find the wayout? I got same question when invoke [[NSUserDefaults standardUserDefaults] setObject:value forKey:key] in sub thread.
That crash report suggests that you’re crashing here. This is deep within the Objective-C runtime, where it’s doing a pointer authentication on a class pointer. This is usually due to some sort of memory management bug, but as to whether that’s your bug or a bug in the system it’s hard to say. We’re deep in KVO here, and KVO has known race conditions that could cause a crash like this.
To start, I recommend that you test your app thoroughly with the standard memory debugging tools. The goal here is that, if there is a memory mangement bug on your side, this will help flush it you so that you can fix it.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
I've noticed that AppStorage uses KVO to observe NSUserDefaults. Is it possible that using AppStorage causes writing to NSUserDefaults to no longer be thread-safe, since SwiftUI will get notified on the wrong thread?
After further investigation, I have confirmed the following (submitted as FB12348064):
The AppStorage property wrapper uses KVO to observe UserDefaults. This makes writing to UserDefaults unsafe on non-main threads, even if the AppStorage is not using the same key as is being written. Any write to UserDefaults causes a lookup of all observers. If the AppStorage is deallocated during that lookup, there will be a crash.
The following reliably crashes for me within a few hundred iterations, tested with both Xcode 14.3.1 and 15b1:
import SwiftUI
struct ContentView: View {
@State var n: Int = 0
// This song-and-dance is to make sure that AppStorageView is destroyed and recreated.
// The two views are visually identical to make the output easier to read. One has @AppStorage,
// the other does not. This causes very fast registering/deregistering from UserDefaults KVO.
func bodyView() -> AnyView {
if n % 2 == 0 {
return AnyView(
ForEach(0..<10) { _ in
AppStorageView(n: n)
})
} else {
return AnyView(
ForEach(0..<10) { _ in
NoAppStorageView(n: n)
})
}
}
var body: some View {
bodyView()
.task {
// Churn UserDefaults on a background thread.
Task.detached {
while true {
UserDefaults.standard.set(Date(), forKey: "randomOtherUserDefaultsKey")
await Task.yield()
}
}
// At the same time, churn the Views to create and destroy AppStorage observations.
while true {
n += 1
await Task.yield()
}
}
}
}
// View with @AppStorage observation
struct AppStorageView: View {
var n: Int
@AppStorage("appStorageValue") var appStorageValue = false
var body: some View { LogView(n: n) }
}
// View without @AppStorage observation
struct NoAppStorageView: View {
var n: Int
var body: some View { LogView(n: n) }
}
struct LogView: View {
var n: Int
var body: some View {
HStack {
Text("App Storage Test: \(n)")
Spacer()
}
}
}