NSError and proper cleanup

  • Hi everyone,

    I'm having some trouble fully understanding how to handle errors using
    NSError and the Error-Responder chain. I have an application whose
    main window is in MainMenu.nib. Most of the interaction with this
    window is handled by an NSObject subclass called MainWindowController
    which is instantiated in MainMenu.nib. For example, I have a menu
    option that brings up a window which displays images from iSight. Note
    that references to a SequenceGrabber are based on that provided in
    WhackedTV at http://developer.apple.com/samplecode/WhackedTV.

    So, choosing a particular menu option will send a
    debugTestWebcamWindow: message, shown below.

    MainWindowController.m
    static TestCamWindowController *tcwc = nil;

    -(void)debugTestWebcamWindow:(id)sender
    {
    if(!tcwc)
      tcwc = [[TestCamWindowController alloc]
    initWithWindowNibName:@"TestCam"];

    [tcwc startVideo];
    }

    which will in turn send an initWithWindowNibName: message, shown below.

    TestWindowCamController.m (subclass of NSWindowController)
    - (id)initWithWindowNibName:(NSString *)windowNibName {
    self = [super initWithWindowNibName:windowNibName];
    if (self != nil) {
      ...
    }
    return self;
    }

    Then awakeFromNib:

    - (void)awakeFromNib
    {
    .
    .
    .

    sgController = [[SGController alloc] init];

    NSError *error = nil;
    BOOL success = [sgController addVideoTrackToPreview:preview
    scaleToFit:YES error:&error];
    if(!success && error) {

      [sgController release];
      sgController = nil;

      [self presentError:error];
    }
    }

    Now, let's suppose that addVideoTrackToPreview:scaleToFit:error:
    fails, say, because we're trying to acquire the camera, but it's in
    use by another application - or for some other reason. At this point,
    I'd like to inform the user that there is a problem and clean up any
    memory that was allocated but will no longer be used.

    Right away, I can [sgController release], no problem there. But I
    would still like to release tcwc (TestCamWindowController). So, I [...
    presentError:error] to start sending the error up the Error-Responder
    chain.

    This sends willPresentError: to self (there is none in this case) and
    then sends presentError: to its superview (NSWindowController?) and so
    on up the chain.

    After this, it goes to the Application's delegate, which for my
    application is NOT MainWindowController (I have another class,
    AppDelegate).

    So, where is my [tcwc release] supposed to go? Was I supposed to
    include a pointer to tcwc in my NSError object so that I can
    eventually release it in some unrelated view, window controller or
    application delegate? This doesn't make sense to me.

    Using exceptions, I would have cleaned up my mess right in
    debugTestWebcamWindow:. So I must be missing something conceptually.
    I've read the Error Handling Programming Guide for Cocoa several times
    now and still do not get it. Is it me or is that guide missing
    something key? :-)
  • On Nov 28, 2007, at 03:35, Ryan Homer wrote:

    > Hi everyone,
    >
    > I'm having some trouble fully understanding how to handle errors
    > using NSError and the Error-Responder chain. I have an application
    > whose main window is in MainMenu.nib. Most of the interaction with
    > this window is handled by an NSObject subclass called
    > MainWindowController which is instantiated in MainMenu.nib. For
    > example, I have a menu option that brings up a window which
    > displays images from iSight. Note that references to a
    > SequenceGrabber are based on that provided in WhackedTV at http://
    > developer.apple.com/samplecode/WhackedTV.
    >
    > So, choosing a particular menu option will send a
    > debugTestWebcamWindow: message, shown below.
    >
    > MainWindowController.m
    > static TestCamWindowController *tcwc = nil;
    >
    > -(void)debugTestWebcamWindow:(id)sender
    > {
    > if(!tcwc)
    > tcwc = [[TestCamWindowController alloc]
    > initWithWindowNibName:@"TestCam"];
    >
    > [tcwc startVideo];
    > }
    >
    > which will in turn send an initWithWindowNibName: message, shown
    > below.
    >
    > TestWindowCamController.m (subclass of NSWindowController)
    > - (id)initWithWindowNibName:(NSString *)windowNibName {
    > self = [super initWithWindowNibName:windowNibName];
    > if (self != nil) {
    > ...
    > }
    > return self;
    > }
    >
    > Then awakeFromNib:
    >
    > - (void)awakeFromNib
    > {
    > .
    > .
    > .
    >
    > sgController = [[SGController alloc] init];
    >
    > NSError *error = nil;
    > BOOL success = [sgController addVideoTrackToPreview:preview
    > scaleToFit:YES error:&error];
    > if(!success && error) {
    >
    > [sgController release];
    > sgController = nil;
    >
    > [self presentError:error];
    > }
    > }
    >
    >
    > Now, let's suppose that addVideoTrackToPreview:scaleToFit:error:
    > fails, say, because we're trying to acquire the camera, but it's in
    > use by another application - or for some other reason. At this
    > point, I'd like to inform the user that there is a problem and
    > clean up any memory that was allocated but will no longer be used.
    >
    > Right away, I can [sgController release], no problem there. But I
    > would still like to release tcwc (TestCamWindowController). So, I
    > [... presentError:error] to start sending the error up the Error-
    > Responder chain.
    >
    > This sends willPresentError: to self (there is none in this case)
    > and then sends presentError: to its superview (NSWindowController?)
    > and so on up the chain.
    >
    > After this, it goes to the Application's delegate, which for my
    > application is NOT MainWindowController (I have another class,
    > AppDelegate).
    >
    > So, where is my [tcwc release] supposed to go? Was I supposed to
    > include a pointer to tcwc in my NSError object so that I can
    > eventually release it in some unrelated view, window controller or
    > application delegate? This doesn't make sense to me.
    >
    > Using exceptions, I would have cleaned up my mess right in
    > debugTestWebcamWindow:. So I must be missing something
    > conceptually. I've read the Error Handling Programming Guide for
    > Cocoa several times now and still do not get it. Is it me or is
    > that guide missing something key? :-)

    [self presentError:error] returns a boolean (see NSResponder docs).
    If someone in the responder chain recovered from the error, you can
    continue with what you were doing. If not, you can cleanup at this
    point.

    Best Regards,

    Nir Soffer
previous month november 2007 next month
MTWTFSS
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
Go to today