32bit device only crash on iOS - ios

I'm receiving crash logs for a bug that I cannot reproduce. The crash only happens on 32bit devices (iPad 4, 3, iPad Mini) so I believe that is a major part of the issue.
The crash occurs on the audio thread, while calculating coefficients for a filter. The filter is composed of a C struct and related functions... once I had an issue with needing to align structs correctly for 32-bit devices, but I'm not sure that's the case here (and I'm not sure how I would test that!)
Beyond that, I'm stumped. Here are the first couple lines of the function in which it crashes. The cos function is the second to last frame of the crash log.
void _calculateWithoutUpdatingSetup(ONCBiquadFilter * filter) {
if (filter->res < 0.01) filter->res = 0.01;
filter->omega = 2 * M_PI * filter->freq / sampleRate;
filter->omegaS = sin(filter->omega);
filter->omegaC = cos(filter->omega);
filter->alpha = filter->omegaS / (2 * filter->res);
///... do a bunch of maths to calculate filter settings
}
And here's the crash log :
18
Crashed: AURemoteIO::IOThread
EXC_BAD_ACCESS KERN_INVALID_ADDRESS 0x0000000000000000
Crashed: AURemoteIO::IOThread
0 myFramework 0x41077a _calculateWithoutUpdatingSetup + 2417
1 libsystem_m.dylib 0x20b229d8 cos + 584
2 myFramework 0x40fa2f ONCBiquadFilterCalculateCoefficients + 14
3 myFramework 0x40fd03 ONCBiquadFilterSetFrequencyAndResonance + 214
4 myFramework 0x414c7b ONCAterotVoiceSetFilterCutoffAndResonance + 206
5 myFramework 0x407677 ONCAterotPolyVoicePlay + 452
6 myFramework 0x3e0d61 ONCAterotLoopStructTick + 1092
7 myApp 0x21333 DSPRenderCallback (ONCAterotAudioController+AudioRenderCallbacks.m:367)
8 myApp 0x20b0f renderCallback (ONCAterotAudioController+AudioRenderCallbacks.m:73)
9 AudioToolbox 0x233224b3 AUInputElement::PullInput(unsigned long&, AudioTimeStamp const&, unsigned long, unsigned long) + 126
10 AudioToolbox 0x234379ab AUMatrixMixer::Render(unsigned long&, AudioTimeStamp const&, unsigned long) + 554
11 AudioToolbox 0x234385a5 AUMatrixMixer::RenderBus(unsigned long&, AudioTimeStamp const&, unsigned long, unsigned long) + 104
12 AudioToolbox 0x23227d01 AUBase::DoRenderBus(unsigned long&, AudioTimeStamp const&, unsigned long, AUOutputElement*, unsigned long, AudioBufferList&) + 148
13 AudioToolbox 0x23227b91 AUBase::DoRender(unsigned long&, AudioTimeStamp const&, unsigned long, unsigned long, AudioBufferList&) + 740
14 AudioToolbox 0x232278a3 AUMethodRender(void*, unsigned long*, AudioTimeStamp const*, unsigned long, unsigned long, AudioBufferList*) + 46
15 myApp 0x65d29 eqCallBack (ONCAterotAudioController+effectCallbacks.m:110)
16 AudioToolbox 0x233224b3 AUInputElement::PullInput(unsigned long&, AudioTimeStamp const&, unsigned long, unsigned long) + 126
17 AudioToolbox 0x233f21b1 AUDynamicsProcessor::Render(unsigned long&, AudioTimeStamp const&, unsigned long) + 308
18 AudioToolbox 0x23227d01 AUBase::DoRenderBus(unsigned long&, AudioTimeStamp const&, unsigned long, AUOutputElement*, unsigned long, AudioBufferList&) + 148
19 AudioToolbox 0x23227b91 AUBase::DoRender(unsigned long&, AudioTimeStamp const&, unsigned long, unsigned long, AudioBufferList&) + 740
20 AudioToolbox 0x232278a3 AUMethodRender(void*, unsigned long*, AudioTimeStamp const*, unsigned long, unsigned long, AudioBufferList*) + 46
21 AudioToolbox 0x23318d89 AUConverterBase::RenderBus(unsigned long&, AudioTimeStamp const&, unsigned long, unsigned long) + 396
22 AudioToolbox 0x23227d01 AUBase::DoRenderBus(unsigned long&, AudioTimeStamp const&, unsigned long, AUOutputElement*, unsigned long, AudioBufferList&) + 148
23 AudioToolbox 0x23227b91 AUBase::DoRender(unsigned long&, AudioTimeStamp const&, unsigned long, unsigned long, AudioBufferList&) + 740
24 AudioToolbox 0x2330864b AURemoteIO::PerformIO(unsigned long, unsigned int, unsigned int, AudioTimeStamp const&, AudioTimeStamp const&, AudioBufferList const*, AudioBufferList*, int&) + 506
25 AudioToolbox 0x23309851 AURIOCallbackReceiver_PerformIO + 596
26 AudioToolbox 0x232ff67b _XPerformIO + 166
27 AudioToolbox 0x23245d69 mshMIGPerform + 184
28 AudioToolbox 0x232d6533 MSHMIGDispatchMessage + 34
29 AudioToolbox 0x23308973 AURemoteIO::IOThread::Run() + 118
30 AudioToolbox 0x2330c331 AURemoteIO::IOThread::Entry(void*) + 8
31 AudioToolbox 0x232238db CAPThread::Entry(CAPThread*) + 186
32 libsystem_pthread.dylib 0x20bbcc7f _pthread_body + 138
33 libsystem_pthread.dylib 0x20bbcbf3 _pthread_start + 110
34 libsystem_pthread.dylib 0x20bbaa08 thread_start + 8
Thanks for any guidance in solving this!
Update : I did notice a couple of mistakes on my part -- freq, res, and sampleRate are all floats, while the rest of the values are doubles. I could see this maybe being part of the issue, though I sort of doubt it as they should just be getting promoted into doubles.

Related

Turning on Thread Sanitizer results in signal SIGABRT

When I create a new Single View App from in Xcode Version 11.3 (11C29) and run it all is ok.
When I turn on Thread Sanitize
And try to run the very same app, I get Thread 1: signal SIGABRT
this is the backtrace
(lldb) bt
* thread #1, stop reason = signal SIGABRT
* frame #0: 0x00007fff523d5bea libsystem_kernel.dylib`__abort_with_payload + 10
frame #1: 0x00007fff523d74f3 libsystem_kernel.dylib`abort_with_payload_wrapper_internal + 80
frame #2: 0x00007fff523d74a3 libsystem_kernel.dylib`abort_with_reason + 19
frame #3: 0x00007fff52469974 libsystem_pthread.dylib`pthread_self.cold.1 + 24
frame #4: 0x00007fff52462fe3 libsystem_pthread.dylib`pthread_self + 34
frame #5: 0x0000000105f2316b libclang_rt.tsan_iossim_dynamic.dylib`__tsan::cur_thread() + 11
frame #6: 0x0000000105ef8985 libclang_rt.tsan_iossim_dynamic.dylib`wrap_sysctlbyname + 37
frame #7: 0x00007fff52470331 libsystem_sim_kernel.dylib`assert_simulator_supported_host + 44
frame #8: 0x00007fff4ff167c1 libSystem.B.dylib`libSystem_initializer + 78
frame #9: 0x0000000105e2a3a7 dyld_sim`ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) + 517
frame #10: 0x0000000105e2a7b8 dyld_sim`ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) + 40
frame #11: 0x0000000105e259a2 dyld_sim`ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 456
frame #12: 0x0000000105e2590f dyld_sim`ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 309
frame #13: 0x0000000105e2590f dyld_sim`ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 309
frame #14: 0x0000000105e2590f dyld_sim`ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 309
frame #15: 0x0000000105e247a6 dyld_sim`ImageLoader::processInitializers(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 188
frame #16: 0x0000000105e24846 dyld_sim`ImageLoader::runInitializers(ImageLoader::LinkContext const&, ImageLoader::InitializerTimingList&) + 82
frame #17: 0x0000000105e19046 dyld_sim`dyld::initializeMainExecutable() + 129
frame #18: 0x0000000105e1d0fc dyld_sim`dyld::_main(macho_header const*, unsigned long, int, char const**, char const**, char const**, unsigned long*) + 3831
frame #19: 0x0000000105e181cd dyld_sim`start_sim + 122
frame #20: 0x000000010e7f68cc dyld`dyld::useSimulatorDyld(int, macho_header const*, char const*, int, char const**, char const**, char const**, unsigned long*, unsigned long*) + 2308
frame #21: 0x000000010e7f4575 dyld`dyld::_main(macho_header const*, unsigned long, int, char const**, char const**, char const**, unsigned long*) + 818
frame #22: 0x000000010e7ef227 dyld`dyldbootstrap::start(dyld3::MachOLoaded const*, int, char const**, dyld3::MachOLoaded const*, unsigned long*) + 453
frame #23: 0x000000010e7ef025 dyld`_dyld_start + 37
(lldb)
I'm I missing something or using Thread Sanitizer incorrectly.
EDIT: I've opened an issue with Apple in their feedback assistant with the ID FB7513235. My open ticket in the feedback assistant indicates there are similar reported issues.
issue resolved in Xcode 11.3.1
Resolved an issue that prevented Xcode from launching processes with
Thread Sanitizer enabled on macOS Catalina 10.15.2. (57822138)
see Xcode 11.3.1 Release Notes

Internationalization CoreText Framework issue iOS 11

Application crashed iOS 11 in CoreText Framework for Hindi Language text
Crashed: com.apple.main-thread
0 CoreText 0x185d393a8 TRunGlue::SeparateCharactersInGlyphRange(CFRange) + 68
1 CoreText 0x185d393a8 TRunGlue::SeparateCharactersInGlyphRange(CFRange) + 68
2 CoreText 0x185d394dc TRunGlue::RotateRight(CFRange, long) + 144
3 CoreText 0x185d9ccf0 OpenTypeShapingEngine::ApplyScriptShaping(unsigned int*) + 308
4 CoreText 0x185d3c654 void TOpenTypeMorph::ApplyShapingEngine<TInlineVector<unsigned int, 30ul> >(OTL::GSUB&, OTL::GlyphLookups&, unsigned int*, CFRange, TInlineVector<unsigned int, 30ul>&, SyncState&, bool*) + 2472
5 CoreText 0x185d3b87c TOpenTypeMorph::ShapeGlyphs(SyncState&, bool*) + 340
6 CoreText 0x185cd8d14 TShapingEngine::ShapeGlyphs(TLine&, TCharStream const&) + 240
7 CoreText 0x185cdd514 TTypesetter::FinishEncoding(std::__1::tuple<TLine const*, TCharStream const*, void const* (*)(__CTRun const*, __CFString const*, void*), void*, std::__1::shared_ptr<TBidiLevelsProvider>*, unsigned int, unsigned char> const&, TLine&, signed char) + 256
8 CoreText 0x185ca833c TTypesetterAttrString::Initialize(__CFAttributedString const*) + 668
9 CoreText 0x185ca7f74 TTypesetterAttrString::TTypesetterAttrString(__CFAttributedString const*) + 112
10 CoreText 0x185ca7e58 CTLineCreateWithAttributedString + 52
11 UIFoundation 0x18ca5e710 -[NSCoreTypesetter _NSStringDrawingCoreTextEngineWithOriginalString:rect:padding:context:forceClipping:usesWebKitCompatibleMetrics:attributes:options:drawingContext:wantsTextLineFragments:validatedAttributedString:firstNonRenderedCharacterIndex:foundSoftHyphenAtEOL:enginePathUsed:] + 840

Crash whilst iOS takes app snapshot

Update: 14th April 2016: Still seeing these crashes in Fabric Crashlytics, and still not sure how I would go about fixing. Seems to be a session crash rate of 0.2%.
As far as I can see, my app is very occasionally crashing when Apple takes a snapshot (as the snippet below is in the crash log). However, I'm not sure how I can stop it from crashing.
[UIApplication _updateSnapshotAndStateRestorationArchiveForBackgroundEvent:saveState:exitIfCouldNotRestoreState:]
I have found a few other posts on SO, but I don't use any kind of WebView (post), does not use any ads, and calls the completionHandler in the main thread. etc. Other people also seem to experience similar issues, but their post remains unanswered. The entire crash log is below. Is this a bug with Apple's internals, or is it something which I can potentially fix?
Thread : Crashed: com.apple.main-thread
0 libsystem_platform.dylib 0x1812962a0 _platform_memmove + 176
1 CoreFoundation 0x181544ed8 CFDataGetBytes + 172
2 CoreFoundation 0x181544ed8 CFDataGetBytes + 172
3 ImageIO 0x182cb599c CGImageReadGetBytesAtOffset + 624
4 ImageIO 0x182cb570c CGImageReadSessionGetBytes + 36
5 ImageIO 0x182d89acc iioReadCallback + 32
6 AppleJPEG 0x182c8bd04 aj_istream_move_to_position + 488
7 AppleJPEG 0x182c8c968 aj_istream_state_restore + 60
8 AppleJPEG 0x182c9b64c applejpeg_decode_set_ra_table + 804
9 ImageIO 0x182d8e1e0 copyImageBlockSetAppleJPEG + 6524
10 ImageIO 0x182cbf130 ImageProviderCopyImageBlockSetCallback + 852
11 QuartzCore 0x183d5ae0c CA::Render::create_image(CGImage*, CGColorSpace*, unsigned int) + 972
12 QuartzCore 0x183d59eec CA::Render::copy_image(CGImage*, CGColorSpace*, unsigned int, double) + 372
13 QuartzCore 0x183d32f00 -[CALayer(CALayerPrivate) _copyRenderLayer:layerFlags:commitFlags:] + 484
14 QuartzCore 0x183d32c54 CA::Context::commit_layer(CA::Layer*, unsigned int, unsigned int, void*) + 108
15 QuartzCore 0x183d2f9cc CA::Layer::commit_if_needed(CA::Transaction*, void (*)(CA::Layer*, unsigned int, unsigned int, void*), void*) + 392
16 QuartzCore 0x183d2f95c CA::Layer::commit_if_needed(CA::Transaction*, void (*)(CA::Layer*, unsigned int, unsigned int, void*), void*) + 280
17 QuartzCore 0x183d2f95c CA::Layer::commit_if_needed(CA::Transaction*, void (*)(CA::Layer*, unsigned int, unsigned int, void*), void*) + 280
18 QuartzCore 0x183d2f95c CA::Layer::commit_if_needed(CA::Transaction*, void (*)(CA::Layer*, unsigned int, unsigned int, void*), void*) + 280
19 QuartzCore 0x183d2f95c CA::Layer::commit_if_needed(CA::Transaction*, void (*)(CA::Layer*, unsigned int, unsigned int, void*), void*) + 280
20 QuartzCore 0x183d2f95c CA::Layer::commit_if_needed(CA::Transaction*, void (*)(CA::Layer*, unsigned int, unsigned int, void*), void*) + 280
21 QuartzCore 0x183d2f95c CA::Layer::commit_if_needed(CA::Transaction*, void (*)(CA::Layer*, unsigned int, unsigned int, void*), void*) + 280
22 QuartzCore 0x183d2f95c CA::Layer::commit_if_needed(CA::Transaction*, void (*)(CA::Layer*, unsigned int, unsigned int, void*), void*) + 280
23 QuartzCore 0x183d2f95c CA::Layer::commit_if_needed(CA::Transaction*, void (*)(CA::Layer*, unsigned int, unsigned int, void*), void*) + 280
24 QuartzCore 0x183d2f95c CA::Layer::commit_if_needed(CA::Transaction*, void (*)(CA::Layer*, unsigned int, unsigned int, void*), void*) + 280
25 QuartzCore 0x183d2f95c CA::Layer::commit_if_needed(CA::Transaction*, void (*)(CA::Layer*, unsigned int, unsigned int, void*), void*) + 280
26 QuartzCore 0x183d2f95c CA::Layer::commit_if_needed(CA::Transaction*, void (*)(CA::Layer*, unsigned int, unsigned int, void*), void*) + 280
27 QuartzCore 0x183d2f95c CA::Layer::commit_if_needed(CA::Transaction*, void (*)(CA::Layer*, unsigned int, unsigned int, void*), void*) + 280
28 QuartzCore 0x183d2f95c CA::Layer::commit_if_needed(CA::Transaction*, void (*)(CA::Layer*, unsigned int, unsigned int, void*), void*) + 280
29 QuartzCore 0x183d2d0cc CA::Context::commit_transaction(CA::Transaction*) + 1332
30 QuartzCore 0x183d2c9dc CA::Transaction::commit() + 512
31 UIKit 0x1865ab768 _UIWindowUpdateVisibleContextOrder + 236
32 UIKit 0x1865ab5b4 +[UIWindow _prepareWindowsPassingTestForAppResume:] + 32
33 UIKit 0x1865e1468 __114-[UIApplication _updateSnapshotAndStateRestorationArchiveForBackgroundEvent:saveState:exitIfCouldNotRestoreState:]_block_invoke_3 + 72
34 libdispatch.dylib 0x181089630 _dispatch_call_block_and_release + 24
35 libdispatch.dylib 0x1810895f0 _dispatch_client_callout + 16
36 libdispatch.dylib 0x18108ecf8 _dispatch_main_queue_callback_4CF + 1844
37 CoreFoundation 0x1815ecbb0 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
38 CoreFoundation 0x1815eaa18 __CFRunLoopRun + 1628
39 CoreFoundation 0x181519680 CFRunLoopRunSpecific + 384
40 GraphicsServices 0x182a28088 GSEventRunModal + 180
41 UIKit 0x186390d90 UIApplicationMain + 204
42 MyApp 0x100095888 main (main.m:16)
43 libdispatch.dylib 0x1810ba8b8 (Missing)
It's a pretty good bet that something somewhere is triggering UIKit manipulations on a background thread. Finding exactly what ... well that's a trick. With a little luck, this gist may be of help.
This is a guard that tracks down UIKit access on threads other than main. This snippet is taken from the commercial iOS PDF framework http://pspdfkit.com, but relicensed under MIT. Works because a lot of calls internally call setNeedsDisplay or setNeedsLayout. Won't catch everything, but it's very lightweight and usually does the job.
If you have any ad display SDKs in your app, that would be an excellent first suspicion. They have a depressing habit of being absolutely horrible at correctly confining UI manipulations to the main thread.

iOS AudioToolbox crashes

I've some crashes in my application in AudioToolbox (AURemoteIO::IOThread), I don't know how to reproduce this crashes, but I have logs from Fabric. Maybe someone is faced with this issue, please help.
Thread : Crashed: AURemoteIO::IOThread
0 AudioToolbox 0x2a5bd1c0 CrashIfClientProvidedBogusAudioBufferList + 119
1 AudioToolbox 0x2a5bd045 AudioConverterConvertComplexBuffer + 268
2 AudioToolbox 0x2a5bd045 AudioConverterConvertComplexBuffer + 268
3 AudioToolbox 0x2a6139cd AUSpatialMixer::Render(unsigned long&, AudioTimeStamp const&, unsigned long) + 1212
4 AudioToolbox 0x2a5bf6b9 AUBase::DoRenderBus(unsigned long&, AudioTimeStamp const&, unsigned long, AUOutputElement*, unsigned long, AudioBufferList&) + 144
5 AudioToolbox 0x2a5bf54d AUBase::DoRender(unsigned long&, AudioTimeStamp const&, unsigned long, unsigned long, AudioBufferList&) + 724
6 AudioToolbox 0x2a5bf26f AUMethodRender(void*, unsigned long*, AudioTimeStamp const*, unsigned long, unsigned long, AudioBufferList*) + 46
7 AudioToolbox 0x2a690303 AUConverterBase::RenderBus(unsigned long&, AudioTimeStamp const&, unsigned long, unsigned long) + 394
8 AudioToolbox 0x2a5bf6b9 AUBase::DoRenderBus(unsigned long&, AudioTimeStamp const&, unsigned long, AUOutputElement*, unsigned long, AudioBufferList&) + 144
9 AudioToolbox 0x2a5bf54d AUBase::DoRender(unsigned long&, AudioTimeStamp const&, unsigned long, unsigned long, AudioBufferList&) + 724
10 AudioToolbox 0x2a685485 AURemoteIO::PerformIO(unsigned long, unsigned int, unsigned int, AudioTimeStamp const&, AudioTimeStamp const&, AudioBufferList const*, AudioBufferList*, int&) + 492
11 AudioToolbox 0x2a68653b AURIOCallbackReceiver_PerformIO + 394
12 AudioToolbox 0x2a67e7b3 _XPerformIO + 166
13 AudioToolbox 0x2a5dd90b mshMIGPerform + 190
14 AudioToolbox 0x2a657735 MSHMIGDispatchMessage + 32
15 AudioToolbox 0x2a685791 AURemoteIO::IOThread::Run() + 120
16 AudioToolbox 0x2a688e3d AURemoteIO::IOThread::Entry(void*) + 8
17 AudioToolbox 0x2a5bb6c5 CAPThread::Entry(CAPThread*) + 208
18 libsystem_pthread.dylib 0x39dbcddf _pthread_body + 138
19 libsystem_pthread.dylib 0x39dbcd53 _pthread_start + 118
I have also frequent crashes in AudioToolbox since iOS 9.
I did open bug reports, but got no solutions, so I asked for developer help.
Apple wrote me on 06-Nov-2015:
"I have checked with engineering. The issue is still under investigation, and there is no resolution available yet."
So I am waiting for a solution or workaround to eliminate the crashes.
My bug report was closed because it was a duplicate, which shows that others have similar problems.

iOS crasher: CFNetwork HTTPReadFilter::doPlainRead(StreamReader*, unsigned char*, long, CFStreamError*, unsigned char*)

I have this crasher which happens a lot in our production app but we are not able to reproduce it. It happened only on iOS8 using iOS8 SDK.
HTTPReadFilter::doPlainRead(StreamReader*, unsigned char*, long, CFStreamError*, unsigned char*) inside CFNetwork. Crashed: com.apple.NSURLConnectionLoader EXC_BAD_ACCESS KERN_INVALID_ADDRESS at 0x00000000
StackTrace:
libsystem_platform.dylib
_platform_memmove + 185
CFNetwork
HTTPReadFilter::doPlainRead(StreamReader*, unsigned char*, long, CFStreamError*, unsigned char*) + 178
CFNetwork
HTTPReadFilter::_streamImpl_Read(unsigned char*, long, CFStreamError*, unsigned char*) + 394
CFNetwork
CoreStreamBase::_streamInterface_Read(unsigned char*, long) + 98
CFNetwork
HTTPNetStreamInfo::_streamImpl_Read(__CFReadStream*, unsigned char*, long, CFStreamError*, unsigned char*) + 306
CFNetwork
CFNetworkReadStream::httpStreamRead(__CFReadStream*, unsigned char*, long, CFStreamError*, unsigned char*, void*) + 44
CoreFoundation
CFReadStreamRead + 328
CFNetwork
HTTPNetStreamInfo::_readStreamClientCallBack(__CFReadStream*, unsigned long) + 128
CFNetwork
CFNetworkReadStream::_readStreamClientCallBackCallBack(__CFReadStream*, unsigned long, void*) + 38
CoreFoundation
_signalEventSync + 146
CoreFoundation
_cfstream_shared_signalEventSync + 342
CoreFoundation
__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 14
CoreFoundation
CFRunLoopRunInMode + 106
CFNetwork
+[NSURLConnection(Loader) _resourceLoadLoop:] + 486
Foundation
__NSThread__main__ + 1118
libsystem_pthread.dylib
_pthread_start + 118
Any help is greatly appreciated!!
That seems to be really an iOS 8 bug. Try to not set a custom size for your NSURLCache. Check this https://devforums.apple.com/message/1102182#1102182

Resources