Following iOS13 release, I'm testing a hybrid app using Cordova. Launching the camera is very slow and generates the following:
=================================================================
Main Thread Checker: UI API called on a background thread: -[UIImagePickerController init]
PID: 1347, TID: 618928, Thread name: (none), Queue name: com.apple.root.default-qos, QoS: 0
Backtrace:
4 0x0000000100f1bba0 +[CDVCameraPicker createFromPictureOptions:] + 124
5 0x0000000100f15d54 -[CDVCamera showCameraPicker:withOptions:] + 108
6 0x0000000100f15570 __25-[CDVCamera takePicture:]_block_invoke_2 + 336
7 AVFoundation 0x00000001b76178f8 2BC0C357-314E-3AE8-B006-C28528B87512 + 710904
8 TCC 0x00000001b35dfbf8 85A762AF-99DB-3B4C-B24B-09600CC17196 + 7160
9 TCC 0x00000001b35e3de4 85A762AF-99DB-3B4C-B24B-09600CC17196 + 24036
10 libxpc.dylib 0x00000001acfe3804 79A1F1AD-9CB4-3334-91D9-E1ED6B1032A3 + 104452
11 libxpc.dylib 0x00000001acfd72c4 79A1F1AD-9CB4-3334-91D9-E1ED6B1032A3 + 53956
12 libdispatch.dylib 0x000000010109b3b4 _dispatch_client_callout3 + 20
13 libdispatch.dylib 0x00000001010b7000 _dispatch_mach_msg_async_reply_invoke + 392
14 libdispatch.dylib 0x00000001010ada8c _dispatch_kevent_worker_thread + 1436
15 libsystem_pthread.dylib 0x00000001ad0e6adc _pthread_wqthread + 336
16 libsystem_pthread.dylib 0x00000001ad0ecc7c start_wqthread + 8
Xcode 10.3
cordova-plugin-camera version 4.1.0
running on iPhone X, iOS13
Eventually the camera opens and allows me to take a photo but the UI is not displayed correctly afterwards. I've tried creating a brand new app with only the camera plugin added and the same thing happens.
How this can be resolved?
It would seem that UIImagePickerController needs to be called in the UI Thread.
Fortunately, the code is already ready for that change!
Just move the cameraPicker init section into the main thread section:
dispatch_async(dispatch_get_main_queue(), ^{
// UI MainThread execution
CDVCameraPicker* cameraPicker = [CDVCameraPicker createFromPictureOptions:pictureOptions];
weakSelf.pickerController = cameraPicker;
cameraPicker.delegate = weakSelf;
cameraPicker.callbackId = command.callbackId;
// we need to capture this state for memory warnings that dealloc this object
cameraPicker.webView = weakSelf.webView;
...
}
D.
Related
EDIT: This appears to be resolved on iOS 13. Leaving all the original details below.
I'm getting a crash when instantiating my CMMotionManager object for Core Motion. This is on an iPhone Xs running iOS 12.0.1.
I can reliably reproduce this with a single-view app, with the following view controller.
import UIKit
import CoreMotion
class ViewController: UIViewController {
var motion: CMMotionManager?
override func viewDidLoad() {
super.viewDidLoad()
// This causes a crash on iPhone Xs, iOS 12.0.1
self.motion = CMMotionManager()
}
}
Full sample project is at https://github.com/doctorcolinsmith/motiontestcrash/tree/master
When running the above, I am getting a fault on a thread with the following output in the debugger.
=================================================================
Main Thread Checker: UI API called on a background thread: -[UIApplication applicationState]
PID: 3634, TID: 630341, Thread name: com.apple.CoreMotion.MotionThread, Queue name: com.apple.root.default-qos.overcommit, QoS: 0
Backtrace:
4 libobjc.A.dylib 0x000000019b0d3894 <redacted> + 56
5 CoreMotion 0x00000001a19337a4 CoreMotion + 305060
6 CoreMotion 0x00000001a1933cd8 CoreMotion + 306392
7 CoreMotion 0x00000001a1933be8 CoreMotion + 306152
8 CoreMotion 0x00000001a19653cc CoreMotion + 508876
9 CoreMotion 0x00000001a196542c CoreMotion + 508972
10 CoreFoundation 0x000000019be6c888 <redacted> + 28
11 CoreFoundation 0x000000019be6c16c <redacted> + 276
12 CoreFoundation 0x000000019be67470 <redacted> + 2324
13 CoreFoundation 0x000000019be66844 CFRunLoopRunSpecific + 452
14 CoreFoundation 0x000000019be675a8 CFRunLoopRun + 84
15 CoreMotion 0x00000001a1964d64 CoreMotion + 507236
16 libsystem_pthread.dylib 0x000000019bae1a04 <redacted> + 132
17 libsystem_pthread.dylib 0x000000019bae1960 _pthread_start + 52
18 libsystem_pthread.dylib 0x000000019bae9df4 thread_start + 4
2018-10-24 16:19:31.423680-0700 motiontest[3634:630341] [reports] Main Thread Checker: UI API called on a background thread: -[UIApplication applicationState]
PID: 3634, TID: 630341, Thread name: com.apple.CoreMotion.MotionThread, Queue name: com.apple.root.default-qos.overcommit, QoS: 0
Backtrace:
4 libobjc.A.dylib 0x000000019b0d3894 <redacted> + 56
5 CoreMotion 0x00000001a19337a4 CoreMotion + 305060
6 CoreMotion 0x00000001a1933cd8 CoreMotion + 306392
7 CoreMotion 0x00000001a1933be8 CoreMotion + 306152
8 CoreMotion 0x00000001a19653cc CoreMotion + 508876
9 CoreMotion 0x00000001a196542c CoreMotion + 508972
10 CoreFoundation 0x000000019be6c888 <redacted> + 28
11 CoreFoundation 0x000000019be6c16c <redacted> + 276
12 CoreFoundation 0x000000019be67470 <redacted> + 2324
13 CoreFoundation 0x000000019be66844 CFRunLoopRunSpecific + 452
14 CoreFoundation 0x000000019be675a8 CFRunLoopRun + 84
15 CoreMotion 0x00000001a1964d64 CoreMotion + 507236
16 libsystem_pthread.dylib 0x000000019bae1a04 <redacted> + 132
17 libsystem_pthread.dylib 0x000000019bae1960 _pthread_start + 52
18 libsystem_pthread.dylib 0x000000019bae9df4 thread_start + 4
(lldb)
Has anyone encountered this before or have an idea on how to solve the crash?
Well, I've tested your application both physical iPhone 6S and iPhone 7 - obviously with iOS 12.0.1. I've also checked for a couple of things in your project and couldn't reproduce your problem at all - not even in simulators - and I don't think it's possible to download a simulator with specific fixes (12.0.x), only with minor version updates - so 12.1 being the next one. This looks really specific on iPhone XS hardware, and I would suggest you to fill an issue with Apple support.
EDIT: Well, I saw that you've already filled a bug report on openradar. This guy even referenced the bug report status on openradar-mirror.
I don't know much about CoreMotion, but the error message tells you you're trying to call a UI action on a background thread. Try putting your code into:
DispatchQueue.main.async {
//your code here
}
It also seems you're trying to do UI related actions in viewDidLoad(). Technically that's fine, but remember that some views probably aren't layed out at that point in time.
I'm using CocoaPods with a React Native app. I've had various errors when running builds in the Xcode simulator. I don't have issues running it on my device. Here's one that I get when I have breakpoints enabled:
- (void)ensureOnJavaScriptThread:(dispatch_block_t)block
{
RCTAssert(_jsThread, #"This method must not be called before the JS thread is created");
The error here is green (yet breaking, thanks Xcode) and it says com.facebook.react.JavaScript (9): breakpoint 1.2
I get two errors when I disable breakpoints, this is one:
void Instance::loadApplication(std::unique_ptr<RAMBundleRegistry> bundleRegistry,
std::unique_ptr<const JSBigString> string,
std::string sourceURL) {
callback_->incrementPendingJSCalls();
SystraceSection s("Instance::loadApplication", "sourceURL",
sourceURL);
nativeToJsBridge_->loadApplication(std::move(bundleRegistry), std::move(string),
std::move(sourceURL));
}
with the red error on the callback_-> line reading EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
the second is this a signal SIGABRT error from this code:
int main(int argc, char * argv[]) {
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
I think i've fixed that issue before by enabling zombies. When I do that, I see this in the console:
2018-07-11 16:56:08.326 [info][tid:main][RCTRootView.m:293] Running application Mapp ({
initialProps = {
};
rootTag = 11;
})
=================================================================
Main Thread Checker: UI API called on a background thread: -[UIApplication setNetworkActivityIndicatorVisible:]
PID: 34682, TID: 5546845, Thread name: (none), Queue name: com.mixpanel.20e6d2c2b6c431dfecfdfaa100ec0a11.0x7fa94db06940.network, QoS: 0
Backtrace:
4 Mapp 0x0000000103a31dd9 -[MPNetwork updateNetworkActivityIndicator:] + 121
5 Mapp 0x0000000103a2ec09 -[MPNetwork flushQueue:endpoint:] + 985
6 Mapp 0x0000000103a2e7b0 -[MPNetwork flushEventQueue:] + 64
7 Mapp 0x0000000103a10418 __32-[Mixpanel flushWithCompletion:]_block_invoke + 312
8 libdispatch.dylib 0x000000010e3f47ab _dispatch_call_block_and_release + 12
9 libdispatch.dylib 0x000000010e3f57ec _dispatch_client_callout + 8
10 libdispatch.dylib 0x000000010e3fdbe5 _dispatch_queue_serial_drain + 1305
11 libdispatch.dylib 0x000000010e3fe4fa _dispatch_queue_invoke + 328
12 libdispatch.dylib 0x000000010e3fa344 _dispatch_queue_override_invoke + 726
13 libdispatch.dylib 0x000000010e40136c _dispatch_root_queue_drain + 664
14 libdispatch.dylib 0x000000010e401076 _dispatch_worker_thread3 + 132
15 libsystem_pthread.dylib 0x000000010e920169 _pthread_wqthread + 1387
16 libsystem_pthread.dylib 0x000000010e91fbe9 start_wqthread + 13
This to me is unreadable. I don't understand what's wrong. Reminder: this build runs without breaking errors on my device, even when breakpoints are enabled. Is this something I should worry about? Please help!
Because in your code UI API called on a background thread. So please disable the Main Thread Checker of xcode. it will work.
Edit Scheme --- > Diagonstics --- > Runtime API Checking ---> Main
Thread Checker (un-check this setting)
Note: Always update the UI inside below method on a background thread
Or
Put your [UIApplication setNetworkActivityIndicatorVisible:] Method inside DispatchQueue.main.async
DispatchQueue.main.async { // Correct
UIApplication.shared.isNetworkActivityIndicatorVisible = true // in swift 4
[UIApplication setNetworkActivityIndicatorVisible:]// in objective-C
}
https://developer.apple.com/documentation/code_diagnostics/main_thread_checker
I really dont know what happened to my app but since I've added the touchid function, app is slower then before and strange writings appear.
I've added a UiViewController before the main controller, so I can check there without show any data to the user until he logged success with touchid.
All right, on my iphone 6s also, but it is very very slow now and it has appeared this on my console after the success of the touchid function:
success!!!!
=================================================================
Main Thread Checker: UI API called on a background thread: -[UIView bounds]
PID: 8460, TID: 1642991, Thread name: (none), Queue name: com.apple.root.default-qos, QoS: 21
Backtrace:
4 LAMer 0x000000010c035d96 _T0So16UIViewControllerC5LAMerE14displaySpinnerSo0A0CAF6onView_tFZ + 54
5 LAMer 0x000000010c060a85 _T05LAMer18AuthViewControllerC13viewDidAppearySbFySbcfU_ + 245
6 LAMer 0x000000010c060e4e _T05LAMer18AuthViewControllerC13viewDidAppearySbFySbcfU_TA + 62
7 LAMer 0x000000010c0374d0 _T0So16UIViewControllerC5LAMerE25authenticationWithTouchIDyySbc10completion_tFySb_s5Error_pSgtcfU_ + 336
8 LAMer 0x000000010c037c2c _T0So16UIViewControllerC5LAMerE25authenticationWithTouchIDyySbc10completion_tFySb_s5Error_pSgtcfU_TA + 108
9 LAMer 0x000000010c037cb3 _T0Sbs5Error_pSgIxyx_SbSo7NSErrorCSgIyByy_TR + 115
10 LocalAuthentication 0x000000010f42edf6 __50-[LAContext evaluatePolicy:localizedReason:reply:]_block_invoke_2 + 72
11 LocalAuthentication 0x000000010f42e2a9 __42-[LAContext evaluatePolicy:options:reply:]_block_invoke_2 + 615
12 LocalAuthentication 0x000000010f4293df __52-[LAClient evaluatePolicy:options:uiDelegate:reply:]_block_invoke + 224
13 libdispatch.dylib 0x00000001124dc2f7 _dispatch_call_block_and_release + 12
14 libdispatch.dylib 0x00000001124dd33d _dispatch_client_callout + 8
15 libdispatch.dylib 0x00000001124e2251 _dispatch_queue_override_invoke + 1458
16 libdispatch.dylib 0x00000001124e9102 _dispatch_root_queue_drain + 772
17 libdispatch.dylib 0x00000001124e8da0 _dispatch_worker_thread3 + 132
18 libsystem_pthread.dylib 0x00000001129a81ca _pthread_wqthread + 1387
19 libsystem_pthread.dylib 0x00000001129a7c4d start_wqthread + 13
=================================================================
Main Thread Checker: UI API called on a background thread: -[UIView initWithFrame:]
PID: 8460, TID: 1642991, Thread name: (none), Queue name: com.apple.root.default-qos, QoS: 21
Backtrace:
4 LAMer 0x000000010c03802d _T0So6UIViewCABSC6CGRectV5frame_tcfcTO + 77
5 LAMer 0x000000010c036064 _T0So6UIViewCABSC6CGRectV5frame_tcfC + 100
6 LAMer 0x000000010c035db3 _T0So16UIViewControllerC5LAMerE14displaySpinnerSo0A0CAF6onView_tFZ + 83
7 LAMer 0x000000010c060a85 _T05LAMer18AuthViewControllerC13viewDidAppearySbFySbcfU_ + 245
8 LAMer 0x000000010c060e4e _T05LAMer18AuthViewControllerC13viewDidAppearySbFySbcfU_TA + 62
9 LAMer 0x000000010c0374d0 _T0So16UIViewControllerC5LAMerE25authenticationWithTouchIDyySbc10completion_tFySb_s5Error_pSgtcfU_ + 336
10 LAMer 0x000000010c037c2c _T0So16UIViewControllerC5LAMerE25authenticationWithTouchIDyySbc10completion_tFySb_s5Error_pSgtcfU_TA + 108
11 LAMer 0x000000010c037cb3 _T0Sbs5Error_pSgIxyx_SbSo7NSErrorCSgIyByy_TR + 115
12 LocalAuthentication 0x000000010f42edf6 __50-[LAContext evaluatePolicy:localizedReason:reply:]_block_invoke_2 + 72
13 LocalAuthentication 0x000000010f42e2a9 __42-[LAContext evaluatePolicy:options:reply:]_block_invoke_2 + 615
14 LocalAuthentication 0x000000010f4293df __52-[LAClient evaluatePolicy:options:uiDelegate:reply:]_block_invoke + 224
15 libdispatch.dylib 0x00000001124dc2f7 _dispatch_call_block_and_release + 12
16 libdispatch.dylib 0x00000001124dd33d _dispatch_client_callout + 8
17 libdispatch.dylib 0x00000001124e2251 _dispatch_queue_override_invoke + 1458
18 libdispatch.dylib 0x00000001124e9102 _dispatch_root_queue_drain + 772
19 libdispatch.dylib 0x00000001124e8da0 _dispatch_worker_thread3 + 132
20 libsystem_pthread.dylib 0x00000001129a81ca _pthread_wqthread + 1387
21 libsystem_pthread.dylib 0x00000001129a7c4d start_wqthread + 13
After this, main controller appear and data of that controller correctly log into console.
Could I ask you what is this code above that appears in my console and if you are already know that touchid make app doing this stuff..
Thank you in advice
This doesn't look like a TouchID issue at all. You are performing UI actions on a background thread. You must call all UI on the main thread.
Look at recent changes to your code and see what you've changed.
Slowness and/or unresponsiveness is classic UI on a background thread issue.
See Main Thread Checker
After upgrading to XCode 9 I suddently get the following warning when I run my app:
Main Thread Checker: UI API called on a background thread: -[UIApplication applicationState]
PID: 15473, TID: 773864, Thread name: com.google.Maps.LabelingBehavior, Queue name: com.apple.root.default-qos.overcommit, QoS: 21
Backtrace:
4 App 0x000000010b8ee524 GMSIsApplicationInBackground + 53
5 App 0x000000010b8dc77a -[GMSForegroundDispatchQueue initWithName:targetQueue:] + 269
6 App 0x000000010b9bc5ee _ZN7gmscore6vector4text8GlyphSetC2ERKNS_4base10reffed_ptrINS0_16TextureAtlasPoolEEEPU28objcproto17OS_dispatch_queue8NSObjectPK8__CTFontff + 344
7 App 0x000000010b9bba58 _ZN7gmscore6vector4text10GlyphCache11GetGlyphSetEPK8__CTFontf + 214
8 App 0x000000010b9b950e _ZN7gmscore6vector4text6GLText14PrefetchGlyphsERKNS_4base10reffed_ptrINS1_10GlyphCacheEEERKNSt3__16vectorItNS9_9allocatorItEEEEPK8__CTFontf + 22
9 App 0x000000010b9b9611 _ZN7gmscore6vector4text6GLText14PrefetchGlyphsERKNS_4base10reffed_ptrINS1_10GlyphCacheEEEPK8__CTLinebf + 207
10 App 0x000000010b9112df _ZN7gmscore6vector12GLPointLabel22PrefetchGlyphsForGroupEPNS0_12GLLabelGroupE + 181
11 App 0x000000010b911207 _ZN7gmscore6vector12GLPointLabel14PrefetchGlyphsEv + 33
12 App 0x000000010b98022a _ZN7gmscore6vector16LabelingBehavior23CreatePendingOperationsERKNSt3__13setINS_4base10reffed_ptrINS0_7GLLabelEEENS2_4lessIS7_EENS2_9allocatorIS7_EEEESE_SE_NS0_13LabelDrawModeE + 1096
13 App 0x000000010b97fb9d _ZN7gmscore6vector16LabelingBehavior14RunLabelingJobERKNS_4base10reffed_ptrINS1_11LabelingJobEEE + 357
14 App 0x000000010b97fa2a ___ZN7gmscore6vector16LabelingBehavior14CommitInternalEPNS_8renderer14EntityRendererE_block_invoke + 22
15 Foundation 0x0000000110bb0948 __NSThreadPerformPerform + 334
16 CoreFoundation 0x00000001117af2b1 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
17 CoreFoundation 0x000000011184ed31 __CFRunLoopDoSource0 + 81
18 CoreFoundation 0x0000000111793c19 __CFRunLoopDoSources0 + 185
19 CoreFoundation 0x00000001117931ff __CFRunLoopRun + 1279
20 CoreFoundation 0x0000000111792a89 CFRunLoopRunSpecific + 409
21 Foundation 0x0000000110b6ae5e -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 274
22 App 0x000000010b9bace5 -[GMSx_GTMSimpleWorkerThread main] + 337
23 Foundation 0x0000000110b788ac __NSThread__start__ + 1197
24 libsystem_pthread.dylib 0x000000011323393b _pthread_body + 180
25 libsystem_pthread.dylib 0x0000000113233887 _pthread_body + 0
26 libsystem_pthread.dylib 0x000000011323308d thread_start + 13
Error Domain=kCLErrorDomain Code=0 "(null)"
I can narrow it down to the problem happens when I assign the map to my view.
override func viewDidLoad() {
super.viewDidLoad()
UIApplication.shared.isIdleTimerDisabled = true
GPSManager.instance.startGPS()
setupLayout()
map = GMSMapView.map(withFrame: CGRect.zero, camera: getCamera(location: initialLocation, zoom: 10))
map.mapType = .hybrid
map.delegate = self
map.settings.consumesGesturesInView = false
self.view.addSubview(map) <-- This is where is goes wrong
self.view.sendSubview(toBack: map)
configureMenus()
}
Is this something I can fix or is it inside Google Maps? Cheers
The problem is inside the Google library.
If you don't want this kind of warning you can disable Main Thread Checker inside the Scheme options.
Go Product > Scheme > Manage Schemes search the Scheme you use for your tests and press Edit... in the left sidebar press Run and then go to Diagnostics and uncheck Main Thread Checker checkbox.
This is only a temporal solution if you don't want these warnings. I do not recommend it because you could introduce bugs if call UI inside a background thread
If you have test you should disable the checkbox in Test option as I explained in Xcode 9, iOS 11, XCUITest failure: Main Thread Checker Flurry Analytics if you do not want the tests crash
I get the following crash:
Exception Type: 00000020
Exception Codes: 0x000000008badf00d
Highlighted Thread: 0
Application Specific Information:
com.[app name].[app name] failed to scene-update in time
Elapsed total CPU time (seconds): 5.050 (user 5.050, system 0.000), 24% CPU
Elapsed application CPU time (seconds): 0.044, 0% CPU
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0:
0 libsystem_kernel.dylib 0x0000000195018e48 semaphore_wait_trap + 8
1 libdispatch.dylib 0x0000000194efbf3c _dispatch_semaphore_wait_slow + 252
2 CFNetwork 0x00000001832a2220 CFURLConnectionSendSynchronousRequest + 284
3 CFNetwork 0x00000001832c27c8 +[NSURLConnection sendSynchronousRequest:returningResponse:error:] + 116
4 Foundation 0x0000000184726358 -[NSData(NSData) initWithContentsOfURL:options:error:] + 308
5 Foundation 0x0000000184726204 +[NSData(NSData) dataWithContentsOfURL:options:error:] + 72
6 [app name] 0x00000001000b1a30 0x100090000 + 137776
7 [app name] 0x00000001001e3f44 0x100090000 + 1392452
8 libdispatch.dylib 0x0000000194eed990 _dispatch_call_block_and_release + 20
9 libdispatch.dylib 0x0000000194eed950 _dispatch_client_callout + 12
10 libdispatch.dylib 0x0000000194ef2208 _dispatch_main_queue_callback_4CF + 1604
11 CoreFoundation 0x00000001838962e8 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 8
12 CoreFoundation 0x0000000183894390 __CFRunLoopRun + 1488
13 CoreFoundation 0x00000001837c11f0 CFRunLoopRunSpecific + 392
14 GraphicsServices 0x000000018cae36f8 GSEventRunModal + 164
15 UIKit 0x0000000188152108 UIApplicationMain + 1484
16 [app name] 0x00000001000dd2ac 0x100090000 + 316076
17 libdyld.dylib 0x0000000194f1aa04 start + 0
On the following code:
#try {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul), ^(void) {
NSData* data = [NSData dataWithContentsOfURL:xxxxxxx options:NSDataReadingUncached error:&error];
...
[self.buffer performSelectorOnMainThread:#selector(addObject:) withObject:data waitUntilDone:YES];
}
#catch (NSException* error) {
NSLog(#"error: %#", error);
}
Yes there is a failure block too, but I simplified the code to the essence, the pure code that causes the crash.
This code runs hundreds of times per hour without any problem. But every now and then it crashes. Always the same crash (like the one above). First, the app freezes, then it crashes. The catch-block is never executed.
The performSelectorOnMainThread uses an object. And that object is added (in the main thread) to an NSMutableArray (self.buffer is an NSMutableArray). I know that NSMutableArrays are not thread-safe and that's why I perform them on the main thread. For waitUntilDone I use YES to prevent the thread from ending before the object is inserted. I used NO too, but that crashes constantly.
Does anyone have an idea why this crash happens? And do you perhaps have a solution for me to prevent this?
Thanks a lot.
You are doing network i/o on the main thread while updating the UI. This takes too long. Don't do that on the main thread. Instead, use an asynchronous way to run the URL fetch and cache the result so it can be used by the next user interface update.
More information:
https://developer.apple.com/library/ios/qa/qa1693/_index.html
Writing to the array on the main thread does not make it thread safe. Use a dedicated dispatch_queue to control access to the nsmutablearray instead, both read and write operations.
https://stackoverflow.com/a/4607664/573988