Daniel Illescas Daniel Illescas - 27 days ago 13
iOS Question

App Crashed at launch, rejected by Apple

I recently updated my app to Swift 4 and made a few changes but for some reason Apple rejects my app because it crashes on an iPad on iOS 10.2... Unfortunately I can only test my app in the iPad Simulator, iPhone simulators and two real iPhones, so I can't test it on a real iPad.

They sent me a crash log, I used a command to Symbolicate the crash (from here: https://medium.com/@nikhilmshchs/symbolicating-ios-crash-reports-e97ad0d6b4dc)

The was the result from the last call from my code :

specialized closure #1 in ScannerViewController.setUpViews() (in QR Code Reader) (ScannerViewController.swift:595)


And this is the line 595 of that method:

case .auto: self.flashButton.setImage(#imageLiteral(resourceName: "FlashAuto"), for: .normal)


This is part of the method:

...
self.flashButton.isEnabled = self.captureDevice?.hasTorch ?? false
self.flashButton.isHidden = true

self.switchCameraButton.isHidden = true

switch UserDefaultsManager.torchModeState {
case .on: self.turnTorch(.on)
case .off: self.turnTorch(.off)
case .auto: self.flashButton.setImage(#imageLiteral(resourceName: "FlashAuto"), for: .normal)
}


More info:
This method is called inside a
DispatchQueue.main.async
call, inside
awakeFromNib()
. The app works perfectly on my iPhone 7 Plus with iOS 11.0 GM and also works on an iPhone 6s with iOS 10.3.3.

I contacted a friend to test the app on a real iPad, but still I don't know why the app should crash on that device and not on my devices...

Maybe I have to set the button image before I hide the button instead of after, but I don't know...

EDIT:

I also check if the device has torch or not:

Inside
self.turnTorch()
:

if device.hasTorch, device.isTorchAvailable, device.isTorchModeSupported(mode) {...}


And inside
flashButtonAction()
:

guard let device = captureDevice, device.hasTorch, device.isTorchAvailable else { return }


EDIT 2:

After some answers, I manually checked (using
UIDevice.current.userInterfaceIdiom
) if the device is an iPad, and if it is, that it should not use the torch... this seems to work fine because Apple hasn't rejected the new build :)

Answer Source

The iPad simply doesn't have the camera flash. So you can't use it. If you are using AVCaptureDevice or something similar, you must make sure that the app won't access the auto flash mode. Or the app will crash.

// Example //
class CameraViewController: BasicViewController, AVCapturePhotoCaptureDelegate {
    @IBOutlet weak var flashSegcontrol: UISegmentedControl! // flashSegcontrol

    func snapPicture() {
        let settingsForMonitoring = AVCapturePhotoSettings()
        if flashSegcontrol.selectedSegmentIndex == 0 {
            if !isDeviceIpad() {
                settingsForMonitoring.flashMode = .on
            } else {
                settingsForMonitoring.flashMode = .off
            }
        }
        else if flashSegcontrol.selectedSegmentIndex == 1 {
            settingsForMonitoring.flashMode = .off
        }
        else {
            if !isDeviceIpad() {
                settingsForMonitoring.flashMode = .auto
            } else {
                settingsForMonitoring.flashMode = .off
            }
        }
        settingsForMonitoring.isAutoStillImageStabilizationEnabled = true
        settingsForMonitoring.isHighResolutionPhotoEnabled = false
        imagePhotoOutput?.capturePhoto(with: settingsForMonitoring, delegate: self as AVCapturePhotoCaptureDelegate)    
    }

    func isDeviceIpad() -> Bool {
        if UIDevice.current.userInterfaceIdiom == UIUserInterfaceIdiom.pad {
            return true
        } else {
            return false
        }
    }
}