问题
I have a huge code base and I want to break on the error "fatal error: unexpectedly found nil while unwrapping an Optional value"
What is the best approach to do that?
I tried adding both: (In the breakpoints sub-window)
- "Add Swift Error Breakpoint"
- "Add Exception Breakpoint"
But that didn't do it. Does that mean that the nil was in some framework code and not my code?
回答1:
Unwrapping optionals gets translated by the compiler into calls to _getOptionalValue(), which calls _preconditionFailure()
in case of anil
value, which gets translated into a call to _fatalErrorMessage()
.
So you need to set breakpoints for _fatalErrorMessage
. The trick here is that you need to set the breakpoints for the mangled name of the function, which is _TTSf4s_s_d_d___TFSs18_fatalErrorMessageFTVSs12StaticStringS_S_Su_T_
.
If you add a symbolic breakpoint for this, the breakpoint will be hit everytime a fatal error occurs. This means you'll catch all nil
unwraps, however you'll also catch some other pieces of code that trigger fatal errors. You should be able to set some conditions on the arguments of the function so that your breakpoint is hit only when the unexpectedly found nil while unwrapping an Optional value
is passed, however I personally didn't played with this feature of lldb
so I'm not sure how you need to set this condition in the breakpoint editor.
Update. In Swift 3 (Xcode 8 beta 6), the breakpoint should be set for _TTSfq4n_n_d_d_n___TFs18_fatalErrorMessageFTVs12StaticStringS_S_Su5flagsVs6UInt32_Os5Never
Here's how you can find out for your own the mangled function name for any Swift version, in order to set a breakpoint to:
- Find you build app location (can be easily found in Xcode Navigator -> Products -> Your App Name.app)
List all your global symbols for the
libswiftCore.dylib
embeded within your app bundle, grep byfatalError
. So for example if your build app is at/Users/your.username/Library/Developer/Xcode/DerivedData/YourApp-randomchars/Build/Products/Debug-iphonesimulator/YourApp.app/
, you should runnm -g /Users/your.username/Library/Developer/Xcode/DerivedData/YourApp-randomchars/Build/Products/Debug-iphonesimulator/YourApp.app//Frameworks/libswiftCore.dylib | grep fatalError
Check the output and grab the mangled method names. There could be more than one symbol, if the function is overloaded. A sample output looks like this:
0000000000032f50 T __TFs18_fatalErrorMessageFTVs12StaticStringS_S_Su5flagsVs6UInt32_Os5Never 00000000001663b0 T __TTSfq4n_n_d_d_n___TFs18_fatalErrorMessageFTVs12StaticStringS_S_Su5flagsVs6UInt32_Os5Never
Make sure you remove the leading underscore before adding the breakpoint, that one comes from the C name mangling (so for the above output you should remain with only one leading underscore for the two symbols).
- Add the breakpoints and force unwrap a nil value, to make sure they work.
Happy nil-unwrapping hunting :)
来源:https://stackoverflow.com/questions/35487780/break-on-any-occurrence-of-fatal-error-unexpectedly-found-nil-while-unwrapping