You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AVCaptureDeviceInput返回nil致部分用户相机功能崩溃求助

Hey there, let's break down the two main issues you're facing—crash in 10% of devices and deviceInputWithDevice returning nil for some users. Here's what I've debugged in similar cases and how to fix them:

1. Why deviceInputWithDevice Returns Nil (and How to Fix It)

This is almost always tied to permissions, device availability, or unhandled errors. Let's cover each scenario:

  • Missing Camera Permissions
    If the user hasn't granted camera access, or has denied/restricted it, creating a capture input will fail silently (or return nil). Always check permission status before initializing your capture session:

    AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    if (status == AVAuthorizationStatusDenied || status == AVAuthorizationStatusRestricted) {
        // Show an alert asking the user to enable camera access in Settings
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Camera Access Required" message:@"Please enable camera access in your device settings to use this feature." preferredStyle:UIAlertControllerStyleAlert];
        [alert addAction:[UIAlertAction actionWithTitle:@"Go to Settings" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
        }]];
        [self presentViewController:alert animated:YES completion:nil];
        return;
    } else if (status == AVAuthorizationStatusNotDetermined) {
        // Request permission first
        [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
            if (granted) {
                // Initialize camera on the main thread
                dispatch_async(dispatch_get_main_queue(), ^{
                    [self setupCameraSession];
                });
            } else {
                // Handle denied permission
            }
        }];
        return;
    }
    
  • Device Already in Use
    If another app (or even another part of your own app) is using the camera, deviceInputWithDevice will return nil. Always capture the error to diagnose this:

    NSError *inputError = nil;
    AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:&inputError];
    if (!deviceInput) {
        NSLog(@"Failed to create capture input: %@", inputError.localizedDescription);
        // Show an alert telling the user to close other apps using the camera
        return;
    }
    
  • Invalid Device or Preset
    Rare, but some older devices might not support AVCaptureSessionPresetPhoto, or defaultDeviceWithMediaType:AVMediaTypeVideo could return nil (e.g., on devices without a camera, though these are rare now). Add checks:

    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    if (!device) {
        // Alert user their device doesn't support camera functionality
        return;
    }
    
    // Verify the session preset is supported
    if (![_session canSetSessionPreset:AVCaptureSessionPresetPhoto]) {
        _session.sessionPreset = AVCaptureSessionPresetHigh; // Fallback to a supported preset
    }
    
2. Fixing the Random Crash Issue

Looking at your code snippet, the most likely culprit is unlocked device configuration and potential thread safety issues:

  • Forgot to Unlock Device Configuration
    You're calling lockForConfiguration:nil, but if the lock succeeds, you never call unlockForConfiguration! Leaving the device locked can cause race conditions, crashes, or failed operations later. Fix this immediately:

    if ([device lockForConfiguration:nil]) {
        if (device.autoFocusRangeRestrictionSupported) {
            device.autoFocusRangeRestriction = AVCaptureAutoFocusRangeRestrictionNear; // Or your desired value
        }
        // Critical: Unlock the device after making changes
        [device unlockForConfiguration];
    } else {
        NSLog(@"Failed to lock device configuration");
    }
    
  • AVCaptureSession Operations on Wrong Thread
    All configuration and state changes for AVCaptureSession (like adding inputs/outputs, starting/stopping the session) must be done on a serial queue (or the main thread—serial queue is better for performance). If you're modifying the session from a background thread, this will cause crashes. Use a dedicated queue:

    // Declare a serial queue as an instance variable
    @property (nonatomic, strong) dispatch_queue_t cameraQueue;
    
    // Initialize it in your setup
    self.cameraQueue = dispatch_queue_create("com.yourapp.cameraQueue", DISPATCH_QUEUE_SERIAL);
    
    // Use it for all session operations
    dispatch_async(self.cameraQueue, ^{
        [_session beginConfiguration];
        // Add inputs/outputs, adjust presets, etc.
        [_session commitConfiguration];
        [_session startRunning];
    });
    
  • Session Not Properly Retained
    If _session is a weak reference, it might get deallocated unexpectedly, leading to crashes. Ensure it's a strong instance variable:

    @property (nonatomic, strong) AVCaptureSession *session;
    
Final Checks
  • Always validate all objects (device, input, output) before using them—never assume they'll be non-nil.
  • Test on older iOS versions (e.g., iOS 13/14) if you're supporting them, as some APIs behave differently.
  • Check crash logs for specific stack traces—they'll point you to the exact line causing the crash (e.g., if it's a null pointer dereference or a thread violation).

内容的提问来源于stack exchange,提问作者Dipen Sekhsaria

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:23:57