1

I have a class to handle movie recording with AVFoundation. The initializer will throw an error if any part of the setup fails. The failure error:

"All stored properties of a class instance must be initialized before throwing from an initialize"

This occurs when trying to create a variable from an initializer that also throws an error if initialization fails.

let captureInputDevice = try AVCaptureDeviceInput(device: device)

Code:

enum MovieRecorderError : ErrorType {
  case CouldNotInitializeCamera
}

class MovieRecorder: NSObject {

  init(previewLayer: UIView) throws {  
    // Scan through all available AV capture inputs
    for device in AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo) as! [AVCaptureDevice] {
      if device.position == .Back {
        do {
          let captureInputDevice = try AVCaptureDeviceInput(device: device)
        } catch {
          throw MovieRecorderError.CouldNotInitializeCamera
        }
      }
    }
  }
}

Question

Is this problem caused by instantiating a variable that throws an error, inside a function that throws an error?

Dan Beaulieu
  • 19,406
  • 19
  • 101
  • 135
Ivan Lesko
  • 1,274
  • 13
  • 26

1 Answers1

4

Is this problem caused by instantiating a variable that throws an error, inside a function that throws an error?

Yes. You are doing a do...catch inside a non-failable initializer. This means there are circumstances remaining where initialization might not correctly take place. You must finish initialization before you can throw. For example, in the code you've shown, if you add super.init() as the first line of the initializer, all is well, because you have finished initialization before throwing.

You might be more comfortable, if initialization can fail, writing a failable initializer (init?).

EDIT: Please note that in starting in Swift 2.2, this requirement will be lifted: it will be legal to throw before finishing initialization.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • I updated the code to show how I am handling the catch statement. – Ivan Lesko Oct 27 '15 at 18:18
  • Okay, revised my answer to match your totally new code. Please try to think about the question _before_ posting next time. – matt Oct 27 '15 at 18:23
  • Hrm, I know Swift 2.2 is upon us soon, but making the initializer failable doesn't seem to change anything unless I'm missing something (unless you're implying returning `nil` rather than throwing, which doesn't communicate the same message). – nhgrif Feb 28 '16 at 15:40
  • @nhgrif My answer to OP's original question included the phrase "all is well because you have finished initialization before throwing". But in Swift 2.2, as I say in the last paragraph, that won't be a concern; it is fine to throw before finishing initialization. – matt Feb 28 '16 at 15:43
  • In my case, I can't manage to figure out how to throw from a class inheriting from `NSObject` and adding its own properties that must be initialized. No ordering or repeating of setting the new property and calling `super.init()` is cutting it. – nhgrif Feb 28 '16 at 15:44
  • Importantly, you can't call `super` before all of the properties are initialized. So if you're trying to assign to a property based off a function that throws, but also need to call `super.init`, it just seems to be impossible. It seems like my question would be a duplicate of this if I posted it, but this answer suggests it's possible... despite that I'm not able to figure it out. – nhgrif Feb 28 '16 at 15:47
  • @nhgrif Would you please go ahead and ask it? (And blip me here so I can pile on.) It's not a duplicate at all: it's about Swift 2.2 in particular. There are definite holes in the way Swift 2.2 is being implemented (see for example my moan here: http://stackoverflow.com/questions/35658334/how-do-i-resolve-ambiguous-use-of-compile-error-with-swift-selector-syntax), and if this is another one, we need to know about it. The worst that can happen is that you answer your own question by saying "this seems to be a bug", something I've often had to do. – matt Feb 28 '16 at 15:59
  • I'm not using 2.2 yet. I can ask a question though. – nhgrif Feb 28 '16 at 16:02
  • Nevermind. I found the mistake I was making. I didn't have a catch-all. – nhgrif Feb 28 '16 at 16:19
  • @nhgrif Cool-o-rama. Thanks for reporting back! – matt Feb 28 '16 at 16:40