What is Partial apply for closure#1 in Swift

Viewed 5804

I am trying to make sense of this crash report but can not make sense, because the function "applySettings()" is not called from init() as is shown in the crash report. What is "partial apply for closure#1" in Swift?

enter image description here

Here is the desired code for init() function.

   public override init()
{
    super.init()
    
    discoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [AVCaptureDevice.DeviceType.builtInWideAngleCamera, AVCaptureDevice.DeviceType.builtInDualCamera, AVCaptureDevice.DeviceType.builtInTelephotoCamera, AVCaptureDevice.DeviceType.builtInDualWideCamera,
            AVCaptureDevice.DeviceType.builtInTripleCamera,
            AVCaptureDevice.DeviceType.builtInUltraWideCamera], mediaType: AVMediaType.video, position: .unspecified)
    
    detectLenses()
    
    checkForDeviceAuthorization()
    
    setZoomParams()
    
    sessionQueue.async { [unowned self] in
        self.configureSession()
    }

}
4 Answers

You cannot do async stuff in an init. We are trying to return the initialized object; that is all you should be doing here. Everything else should happen in some subsequent configuration call when self completely exists.

@DanielKaplan

I am looking for an answer to the TITLE (as is the OP), not the cause of the stack trace. The answer must explain what "partial apply for closure#1" means.

A bit of background (from here, for more deep in math):

enter image description here

So what's going on with?

sessionQueue.async { [unowned self] in
    self.configureSession()
}

Here we have closure calls function directly, swift compiler recognises this and makes currying, ie. instead of call function of function, unwraps closure and injects into async direct call of internal function, like

sessionQueue.async(execute: CapturePipeline.configureSession(self))

but to join this with source code debug info should preserve information about this simplification, so they mark it as partial apply for closure# (where N is just ordered number of existed closures in parent function).

And to fix that crash as said before the best is to remove that part from init at all and call after creation completed. The worse, but depending on other code might be applicable, is to use [weak self].

I got a partial apply for closure resulting from a modulus operation (%) on a nil. Probably not the actual cause though.

I had this:

if myArray.count == 0 {
    return
}
let i = foo % (myArray.count)!

Fixed by changing it to:

if myArray.count == nil || myArray.count == 0 {
    return
}
let i = foo % (myArray.count)!

What helped me see the issue, however, was downloading the dSYM files from TestFlight and uploading them to NewRelic, which showed me the exact line in my own code where the crash happened.

This should be doable in XCode also, but for some reason XCode was not showing me the line number this time.

I'll preface by saying I'm not fully confident in my answer. But after looking around quite a bit, in Swift stacktrace, when a closure immediately executes, it shows up as something like

closure #1 in MyAppTabBarController.initialSetup() + 1028 (MyAppTabBarController.swift:469)

When it's something that doesn't immediately return (like a network call), it shows up as a partial apply, like

partial apply for closure #1 in closure #1 in DataRequest.response(queue:responseSerializer:completionHandler:) + 56 (ResponseSerialization.swift:167)

I'd love for someone to chime in and say confidently that that's the case, but that's my guess.

Related