I have detected a rare crash in my application. The stack trace was not helpful. It is not directly related to my code:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSAttributeDictionary textContainerForAttributedString:containerSize:lineFragmentPadding:]: unrecognized selector sent to instance 0x1b8d89c0'
Last Exception Backtrace:
0 CoreFoundation 0x2e23bfd3 __exceptionPreprocess + 131
1 libobjc.A.dylib 0x38ab2ccf objc_exception_throw + 38
2 CoreFoundation 0x2e23f967 -[NSObject(NSObject) doesNotRecognizeSelector:] + 202
3 CoreFoundation 0x2e23e253 ___forwarding___ + 706
4 CoreFoundation 0x2e18d7f8 __forwarding_prep_0___ + 24
5 UIFoundation 0x35e77a25 __NSStringDrawingEngine + 12204
6 UIFoundation 0x35e749a7 -[NSString(NSExtendedStringDrawing) drawWithRect:options:attributes:context:] + 150
7 UIKit 0x30a70d21 -[UILabel _drawTextInRect:baselineCalculationOnly:] + 4224
8 UIKit 0x30ad7009 -[UILabel drawTextInRect:] + 500
9 UIKit 0x30ad6e0b -[UILabel drawRect:] + 78
10 UIKit 0x30ad6da5 -[UIView(CALayerDelegate) drawLayer:inContext:] + 372
11 QuartzCore 0x307042c1 -[CALayer drawInContext:] + 100
12 QuartzCore 0x306ede3f CABackingStoreUpdate_ + 1854
13 QuartzCore 0x307c8d6d ___ZN2CA5Layer8display_Ev_block_invoke + 52
14 QuartzCore 0x306ed6f3 x_blame_allocations + 82
15 QuartzCore 0x306ed39b CA::Layer::display_() + 1106
16 QuartzCore 0x306d103d CA::Layer::display_if_needed(CA::Transaction*) + 208
17 QuartzCore 0x306d0cd5 CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 24
18 QuartzCore 0x306d06df CA::Context::commit_transaction(CA::Transaction*) + 230
19 QuartzCore 0x306d04ef CA::Transaction::commit() + 314
20 QuartzCore 0x306fda83 CA::Transaction::release_thread(void*) + 162
21 libsystem_pthread.dylib 0x390dd68d _pthread_tsd_cleanup + 164
22 libsystem_pthread.dylib 0x390dd40b _pthread_exit + 86
23 libsystem_pthread.dylib 0x390de17d pthread_exit + 28
24 Foundation 0x2eb7846f +[NSThread exit] + 10
25 Foundation 0x2ec24a7d __NSThread__main__ + 1092
26 libsystem_pthread.dylib 0x390de919 _pthread_body + 140
27 libsystem_pthread.dylib 0x390de88b _pthread_start + 102
28 libsystem_pthread.dylib 0x390dcaa4 thread_start + 8
Therefore, I tried to add more debug information to find out more about the crash. I could find traces to viewWillLayoutSubviews
. It is being called in the background. I can just exit from the function if I detect it is in the background. But this is a dirty hack. I want to fix it correctly by preventing "things" from making the app call viewWillLayoutSubviews
in the background thread.
I couldn't yet found those "things" as stacktrace is not helpful.
frame #1: 0x32946d16 UIKit`-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 314
frame #2: 0x325c462a QuartzCore`-[CALayer layoutSublayers] + 142
frame #3: 0x325bfe3a QuartzCore`CA::Layer::layout_if_needed(CA::Transaction*) + 350
frame #4: 0x325bfccc QuartzCore`CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 16
frame #5: 0x325bf6de QuartzCore`CA::Context::commit_transaction(CA::Transaction*) + 230
frame #6: 0x325bf4ee QuartzCore`CA::Transaction::commit() + 314
frame #7: 0x325eca82 QuartzCore`CA::Transaction::release_thread(void*) + 162
frame #8: 0x3af0568c libsystem_pthread.dylib`_pthread_tsd_cleanup + 164
frame #9: 0x3af0540a libsystem_pthread.dylib`_pthread_exit + 86
frame #10: 0x3af0617c libsystem_pthread.dylib`pthread_exit + 28
frame #11: 0x30a6746e Foundation`+[NSThread exit] + 10
frame #12: 0x30b13a7c Foundation`__NSThread__main__ + 1092
frame #13: 0x3af06918 libsystem_pthread.dylib`_pthread_body + 140
frame #14: 0x3af0688a libsystem_pthread.dylib`_pthread_start + 102`
What can be those "things"?
This kind of crash occurs when you call something in the background that must run on the main thread.
Finding the exact line may be almost impossible. I found the result with lots of NSLog
lines and [NSThread isMainThread]
lines.
Calling almost anything on UI elements (especially those require size calculations/changes, triggers viewWillLayoutSubviews
. In my case it was both UIImageViews and UILabels.
If you can't find where you make UI updates in the background, check if you post NSNotification
s in the background.