NSError.setUserInfoValueProvider(forDomain:provider:)
was introduced in MacOS 10.11/iOS 9 as a way to populate the userInfo
dictionary of an NSError
for the given error domain using a block, thereby avoiding a lot of boilerplate and repetition in code that may throw.
I tried to use it like this:
if NSError.userInfoValueProvider(forDomain: "Test") == nil {
NSError.setUserInfoValueProvider(forDomain: "Test"){ err, userInfoKey in
print("This is an error:", err, userInfoKey)
return nil
}
}
The call site looks like this:
throw NSError(domain: "Test", code: 0, userInfo: nil)
When the error is thrown, the log is filled with "This is an error:", but the error itself or the userInfoKey
is never printed out. The program finally aborts with a final message in the log:
warning: could not execute support code to read Objective-C class data in the process. This may reduce the quality of type information available.
The problem is that printing err
in
print("This is an error:", err, userInfoKey)
calls the same value provider recursively, because the string representation of the error is determined. The program then eventually crashes with a stack overflow. You can verify that by setting a breakpoint on that line.
If you change the line to
print("This is an error:", userInfoKey)
then everything works as expected.