Collection <__NSArrayM: 0x170e45d00> was mutated while being enumerated - UIImagePickerConteroller didFinishPickingMediaWithInfo - ios

I have a native Objective-C application that takes photo using UIImagePickerConteroller. Once UIImagePickerController didFinishPickingMedia delegate function return image, I am storing the image in my app document directory and storing the the image location in an array so that I can show it in my application gallery view.
NOT frequently, but once or twice in a month I am receiving a crash log in AppSee/Fabric crash tracker, after user finished taking photo.
In Appsee video I can see where exactly the crash happened. Crash log says NSArray was mutated while being enumerated(Check the attached image). Now I am NOT doing any addObject or removeObject functionality to my photo mutableArray at the time of enumeration. I am doing a mutable copy of my photo array before reading data to show it my photo gallery. So no chance of mutation while being enumerated.
According to the crash log, it seems like the issue is related to UIImagePickerController. Because the log said -
-[CAMPriorityNotificationCenter _postNotification:forEntries:]
-[CAMPriorityNotificationCenter _notificationReceiver:]
And 'CAMPriorityNotification' is used by UIImagePickerController class. But not sure if UIImagePickerController is throwing an error and causing crash. I putted #try #catch in didFinishPickingMedia function to find the crash issue. But #try #catch is not throwing an error. So that is making more confusion to me.
Is there anyone faced similar type of crash issue after taking photo? Any suggestion i would appreciate.

This is an apple issue. Apple responded to my bug report. Here is the response from them -
"Engineering has determined that your bug report (31369562) is a duplicate of another issue (29753773) and will be closed.
The open or closed status of the original bug report your issue was duplicated to appears in the yellow "Duplicate of XXXXXXXX" section of the bug reporter user interface. This section appears near the top of the right column's bug detail view just under the bug number, title, state, product and rank."

Try to set your reference to UIImagePickerController* to nil in 2 cases:
when you have received image from controller - in function
"didFinishPickingImage"
when you go to background or go back from screen that have link to UIImagePickerController via property. I did it in call viewDidDissapear:
- (void)viewDidDissapear:(BOOL)animated {
[super viewDidDissapear: animated];
self.photoPicker = nil; // that property of type UIImagePickerController*
}



I had a lot of crashes in CAMPriorityNotificationCenter, all in background. After these 2 changes (mentioned above) - crashes didn't appear.

So I was getting this iOS 14 and 15 regularly until I changed my code to not do anything in the completion handler. I used to do my image saving/processing in there.
This is how it was written:
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info {
[picker dismissViewControlle Animated:YES
completion:^{
// Process and Save Image
}];
}
And now I have changed it to:
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info {
if (picker.isBeingDismissed) {
return;
}
[picker dismissViewControllerAnimated:YES
completion:nil];
// Process and save image
}
I was getting this crash a couple of times a week and now its been about 2 weeks without a crash.
Update - so I'm still getting these about once a fortnight now. All on 14.* devices...

It looks like your code may access an collection and modify it at the same time.

Related

bool _WebTryThreadLock(bool) crash

I'm seeing some crashes in my App crash tracking tool. Basically I have a tabBarController, one of the tabs has an embedded UIWebView, another tab has a controller with a UITableView. So what happens is that when user goes to the WebView first, and it starts loading, after a few seconds they go to the tableView controller, the crash randomly happens.
Judged by the timing I saw in crash log, it seems that the webView is about to finish loading when the user taps the UITableView tab, so I inserted a code into the didFinishLoading. This way I can reliably reproduce the crash. The code looks like this:
The webViewController:
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[tabBarController gotoTableViewController];
}
The tableViewController:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.tableView reloadData];
}
Here is the crash:
bool _WebTryThreadLock(bool), 0x1700113d0: Multiple locks on web thread not allowed! Please file a bug. Crashing now...
I don't know what I can do about it, it seems both the webView and tableView are locking the mainThread? Is there a way to "unload" the webView loading from main thread? I've tried stopLoading, not working...
Found it. It was indeed caused by the file parsing on mainThread. My file parsing is utilising NSRunLoop to parse a XML file. However the file is meant to be used as a cached values and needed to be parsed synchronously, so I put it on mainThread. I tried to put it onto a background thread and use dispatch_sync, the crash's still there. So I tried dispatch_async with a dispatch_semaphore_t, the crash was gone!
I had the same issue, and I also had an NSRunLoop that could potentially ran while the WebView was fetching the data.
Removing the NSRunLoop the problem is now fixed, but I don't understand why the problem happens in first place.
#KKRocks could you elaborate a bit why the NSRunLoop should cause the WebView to run in background?

multiple pictures with UIImagePickerController

i've been searching around the web but couldn't find an answer.
basically i wanna take two photos one right after the other.
i'm using UIImagePickerController to show a picker and implementing didFinishPickingMediaWithInfo.
when it gets called i'm checking my count so that if its one, i implement a block and pass it to dismissViewControllerAnimated like this:
if(1 == count) {
void (^simpleBlock)(void);
simpleBlock = ^{
[self useCamera];
};
[self dismissViewControllerAnimated:NO completion:simpleBlock];
}
it all seems to work fine, and even the useCamera method is called.
the problem is that the second time the picker shows i see all of its controls but i don't see on the screen the image from the camera.
any help would be appriciated.
i managed to work it out with replacing the call to useCamera with:
[self performSelector:#selector(useCamera) withObject:nil afterDelay:0.3];
i think my question has some relation to: iOS 7 UIImagePickerController has black preview
since the delay fixed the problem.
For you to save time. You can use available library out there. These are my good choices. CTAssetsPickerController ELCImagePickerController
UIImagePickerController helps to access the default camera app in iOS.
It will allow only limited functionalities like take picture/video, photo album.

iOS: idleTimerDisabled = YES works only until ImagePicker was used

I have an iPad survey tool as an internal enterprise application. I prevent screen locking with setting [[UIApplication sharedApplication] setIdleTimerDisabled: YES]; at didFinishLaunchingWithOptions of the application delegate.
That works fine until I use the imagePicker to take an image. After that, the idleTimer is activated again. I have tried to disable it after the image was taken but that doesn't work.
Here I found the hint that setting the required device capabilities in the info.plist could help. But so far it didn't. I have just added all camera specific flags.
Any ideas?
Many thanks!
Marcus
I was able to reset the UIApplication idleTimerDisabled like so:
- (void)resetIdleTimerDisabled
{
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
}
#pragma mark - UIImagePickerControllerDelegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[self dismissViewControllerAnimated:YES completion:^{
[self performSelector:#selector(resetIdleTimerDisabled) withObject:nil afterDelay:1.0];
}];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[self dismissViewControllerAnimated:YES completion:^{
[self performSelector:#selector(resetIdleTimerDisabled) withObject:nil afterDelay:1.0];
}];
}
What I suspect is happening is that internally UIImagePickerController sets UIApplication.idleTimerDisabled to YES to keep the camera from sleeping. When finished (after the delegate methods are called and apparently even after the animation completion block is executed), the UIImagePickerController sets UIApplication.idleTimerDisabled back to NO. Instead, it only should do this if the value was previously NO.
I filed a bug report with Apple. See UIImageViewControllerBug sample project.
Jamie's solution looks good! I'm just not a big fan of afterDelay: methods:)
The issue is in the PhotoLibrary framework: it disables the idleTimer prior to starting preview stream from camera and enables it again when tearing it down regardless of the previous value.
If you feel more adventures and want solution that works throughout the app, here is one involving swizzling: https://gist.github.com/zats/1a4aece697075478b44a
Tested for both cases when idleTimer disabled or enabled prior to showing image picker. My solution does not observe idleTimerDisabled while image picker is presented.
P.S. the same issue happens when using dictation feature (bug in UIDictationController)
(#jamie-mcdaniel if you would be so kind to update your bug report)

Using Instruments to trace memory leak Xcode5 and iOS7

I developed my first app and still learning. Just updated Xcode 5 yesterday and my iPhone 5 is running iOS 7.1. I am now working on understanding the Instruments tool to analyze my app. I am using the Leak profile in Instruments and have come across a retain cycle and leak which I can't figure out. Appreciate any help I can get to understand a) how to pinpoint the bug and b) what I did wrong and how to avoid it in the future.
In my app, I am using the camera to take a pic. While the camera is up, I tapped on the screen to focus and that is when I noticed the leak pop up in Instruments. Looks like there is a retain cycle not in my code (if I understand correctly) and a root leak in my code which I don't understand.
I am using ARC, so I should not have to release "picker" in the part of my code that Instruments is pointing me to (part 2 below, with code).
What can I do about the retain cycle. It is not in my code, but am I still the cause of it? Does it stem from the "root leak?" If I am NOT responsible for it, what's should I do about it?
My only code in this stack trace does not help me understand where the leak is coming from. The line is Instruments points me to in my code is [picker dismissViewControllerAnimated:YES completion:nil]; in my imagePickerController:didFinishPickingMediaWithInfo: method. I am pasting the code below.
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *pickerImage = [info objectForKey:
UIImagePickerControllerOriginalImage];
_imageView.image = pickerImage;
[picker dismissViewControllerAnimated:YES completion:nil]; // <--- mem-leak
}
EDIT - Code where I create my UIImagePickerController.
- (IBAction)snapPicture:(id)sender
{
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
// If the camera button was tapped AND we have a camera, use it...
if ((sender == _cameraButton) && [UIImagePickerController
isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
[imagePicker setSourceType:UIImagePickerControllerSourceTypeCamera];
} else {
[imagePicker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
}
imagePicker.delegate = self;
// bring up the image picker view
[self presentViewController:imagePicker animated:YES completion:nil];
}
Here's my theory: what you've encountered is evidently a bug (or flaw) in Apple's own code, and all you can do is laugh maniacally and forget about it.
To test my theory, I ran my own code, written totally separately and at a different time. It does almost the same thing your code does: it lets the user take a picture, and puts the image into the interface. Here's my code:
https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/bk2ch17p702takeAPicture/ch30p962takeAPicture/ViewController.m
I ran my code under Instruments with the Leaks instrument, and guess what? I saw the same issues you did.
Naturally, I then started searching on Stack Overflow, and all of this turns out to be old ground. For example:
UIImagePickerController memory leak on iOS5
Even Apple's own sample code, called PhotoPicker (or Using UIImagePickerController to Select Pictures and Take Photos) has the same leak.

UIImagePicker Controller with the Delete option

I am building an app which takes the image from the UIImagePickerControllerSourceTypePhotoLibrary . When I select the Image I have to display the Image in another view with the Delete button . Please refer the below image . My intension is if you observe the photos app in the iPhone after selecting the image it is going to the fullImage view . Can we display the same in the app using the UIImagePickerController?
I have searched a lot but didn't get any solution . Is there any frameworks existing for showing full Image with the Delete symbol . I am trying to implement my own view, but it is taking much time to implement .
See this library
FGallery
There is the trash button which you are looking. You need to do only small changes for your requirement
You can get the selected image from your library, you have to dismiss your
UIImagePickerController and after that you need to create custom UIViewController and you have to present/push it to the user with saved picture:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[picker dismissViewControllerAnimated:YES completion:^{}];
UIImage *_image = [info objectForKey:UIImagePickerControllerEditedImage];
UICustomViewController *custom = [[UICustomViewController alloc] init];
custom.MyImage = _image;
[self presentViewController:custom animated:YES completion:nil];
}
It's very simple solution and you don't needy to use any existing framework.
Apple doesn't actually allow you to delete from the photo library through an API. The user has to actually go to the Photos app and delete it manually themselves. Apple does allow you write to the photo library:
To save a still image to the user’s Saved Photos album, use the
UIImageWriteToSavedPhotosAlbum function.
To save a movie to the user’s Saved Photos album, use the UISaveVideoAtPathToSavedPhotosAlbum function.
But for deleting and editing/overriding an existing photo, Apple doesn't have anything like that right now.

Resources