26

When i try to load camera from my code, camera preview is black. If I wait for 10-20 seconds it will show real camera preview. I found several questions and some of them suggest that running some other code in background should be the reason for this. However I don't have any code running in background. How should I fix this?

This is my code where I run camera

UIImagePickerController *photoPicker = [[UIImagePickerController alloc] init];

photoPicker.delegate = self;
photoPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:photoPicker animated:YES completion:NULL];
daveMac
  • 3,041
  • 3
  • 34
  • 59
user2689024
  • 261
  • 3
  • 5
  • This code looks right - I would suggest trying this: `dispatch_async(dispatch_get_main_queue(), ^{ });` and seeing if anything changes. If it works right, that means that you *are* running the code in the background *somewhere* – Undo Feb 19 '14 at 17:54
  • You can also set a breakpoint on any of the lines you posted, and look in the Xcode sidebar when you hit the breakpoint to see what thread you are on. – Zev Eisenberg Feb 19 '14 at 18:02
  • @Undo I have tried your code and nothing changed. – user2689024 Feb 19 '14 at 18:14
  • @ZevEisenberg also tried with breakpoint and it says I am on Thread 1. – user2689024 Feb 19 '14 at 18:15
  • 10
    Welcome to the crap that is iOS 7's UIImagePicker. For absolutely no apparent reason, sometimes (more often than not) you get a black preview screen. Sometimes it goes away after awhile and you get the camera preview, and sometimes it doesn't. Mind you, the exact same code works seamlessly on iOS 6. I have spent hours trying to figure this out. This question deserves some serious attention! It makes us developers look like we don't know how to program, when it is entirely in Apple's hands. I am thinking of writing my own image capture with lower level API's. – daveMac Feb 19 '14 at 20:05
  • One more thing, if you take a picture while the screen is black, it still shows up fine, so it's just the preview. – daveMac Feb 19 '14 at 20:07
  • 2
    Yes, it shows up fine when I take the picture. I have also tried implementing AVFoundation camera and it also needs 10-20 seconds until it shows preview. I can't believe there is no solution for this issue. – user2689024 Feb 21 '14 at 19:24
  • Check my answer: preview runs on main thread so borks easy. You have to implement a semaphore to lockout shared access or wait for Apple to fix it – davbryn Feb 24 '14 at 20:31
  • maybe use completion:nil instead of NULL. I don't know if it's a difference but I have never used or seen NULL in a completion. – Jonathan Gurebo Feb 28 '14 at 21:35
  • There is a similar question on other thread on SO http://stackoverflow.com/questions/16746839/idevice-camera-shows-black-instead-of-preview Try creating a singleton instance of UIImagePickerController and use it. The possible problem possibly can occurs when an app uses many threads or dispatch queues – Pawan Sharma Mar 03 '14 at 12:22
  • Does your app uses multiple treads or dispatch queues. If so then check if you are not showing the UIImagePicker on main thread. – Pawan Sharma Mar 03 '14 at 12:26
  • possible duplicate of [iOS 7 UIImagePickerController has black preview](http://stackoverflow.com/questions/19081701/ios-7-uiimagepickercontroller-has-black-preview) – Mike Hay Sep 11 '14 at 01:52

3 Answers3

21

About 5 months ago my team discovered a memory leak with UIImageViewController in iOS7. Each instantiation slowed down the app exponentially (i.e. first alloc-init had a 1 second delay, second had a 2 second delay, third had a 5 second delay). Eventually, we were having 30-60 delays (similar to what you're experiencing).

We resolved the issue by subclassing UIImagePickerController and making it a Singleton. That way it was only ever initialized once. Now our delay is minimal and we avoid the leak. If subclassing isn't an option, try a class property in your viewController and just lazy load it like so.

-(UIImagePickerController *)imagePicker{
    if(!_imagePicker){
        _imagePicker = [[UIImagePickerController alloc]init];
        _imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
    }
    return _imagePicker;
}

Then you can just call it later like:

[self presentViewController:self.imagePicker animated:YES completion:nil];
ebandersen
  • 2,362
  • 26
  • 25
  • 1
    Thank you @eckyzero for your answer. I have a feeling that it reduced some time I have to wait for black screen to remove, but it hasn't been completely resolved. It seems that it is a more responsive with your code – user2689024 Feb 26 '14 at 20:01
  • This isn't a complete fix, but it certainly helps. —It doesn't feel like too much to ask for Apple to put this issue at the very top of their list of fixes for the next update of iOS 7. It is really important to have such key features of apps work quickly and efficiently! Furthermore, this isn't the only bug with the UIImagePickerController in iOS 7. – daveMac Mar 03 '14 at 15:22
  • I'm glad to have helped a little bit and I couldn't agree with you more. Do you know if anyone has filed a bug with Apple? – ebandersen Mar 03 '14 at 16:19
2

Had this myself - it happens if something is running on the main dispatch thread - are you resizing images by any chance?

It puts the preview onto the main thread and if something is using it, you get a black screen. It's a bug and the workaround is to either take over the main thread or to disable the photo picker until the queue is free

davbryn
  • 7,156
  • 2
  • 24
  • 47
  • In this view I am using UICollectionView and yes I am resizing images as well. I have checked and my UIImagePicker code is running on the main thread. Do you have any ideas could be there something wrong with resizing images? – user2689024 Feb 26 '14 at 20:03
  • I'm looking for a solution myself - at the moment is seems that it is an internal bug. I can't seem to resize images on another thread or use AVAssetWriter at the same time: very annoying – davbryn Feb 26 '14 at 20:37
  • I'm facing a similar problem (closed due to memory issues), but only if I resize the captured image. What does this mean for me? No image resizing here? – swalkner Apr 29 '14 at 14:00
-1

This Should work for you:

    - (void)cameraViewPickerController:(UIImagePickerController *)picker
{
    [self startCameraControllerFromViewController: picker
                                    usingDelegate: self];
}


- (BOOL) startCameraControllerFromViewController: (UIViewController*) controller
                                   usingDelegate: (id <UIImagePickerControllerDelegate,
                                                   UINavigationControllerDelegate>) delegate {

    if (([UIImagePickerController isSourceTypeAvailable:
          UIImagePickerControllerSourceTypeCamera] == NO)
        || (delegate == nil)
        || (controller == nil))
        return NO;


    UIImagePickerController *cameraUI = [[UIImagePickerController alloc] init];
    cameraUI.sourceType = UIImagePickerControllerSourceTypeCamera;

    // Displays a control that allows the user to choose movie capture
    cameraUI.mediaTypes = [[NSArray alloc] initWithObjects: (NSString *) kUTTypeImage, (NSString *) kUTTypeMovie,nil];

    // Hides the controls for moving & scaling pictures, or for
    // trimming movies. To instead show the controls, use YES.
    cameraUI.allowsEditing = NO;

    cameraUI.delegate = delegate;

    [controller presentViewController:cameraUI animated:YES completion:nil];
    return YES;
}
Suhaiyl
  • 1,071
  • 9
  • 17
  • 1
    I also solved issue. I was having issue of background thread.Uploading images task i put it in background thread. i put it back on main thread and working fine. – Nirav Jain Mar 25 '14 at 14:00