JiuJitsuCoder
JiuJitsuCoder

Reputation: 1876

NSError won't clear out old error

Long time listener, first time caller here so forgive me if I am not being explicit enough. I am currently scratching my head over an issue with NSError objects. Here is how things are setup:

-(void)mainMethod {
   NSError *myError = nil;
   NSString *myString = @"A really great string. 1234.";
   if ([self parseAndStoreString:myString error:&myError] == NO) {
      [self popupWithErrorMessage:[[myError localizedDescription] copy]];
   }

-(BOOL)parseAndStoreString:(NSString *)incomingString error:(NSError *__autoreleasing *)err {
   if ([self setupSomething error:err] == NO) {
      return NO;
   }
   if ([self doSomethingWithString:incomingString error:err] == NO) {
      return NO;
   }
   if ([self storeString:incomingString error:err] == NO) {
      return NO;
   }
}

-(BOOL)doSomethingWithString:(NSString *)incomingString error:(NSError *__autoreleasing *)err {
   if (incomingString == nil) {
     DLog(@"String was null! See? : %@", incomingString);
     NSDictionary *errorInfo = [NSDictionary dictionaryWithObject:EDEmptyStringErrorDescription forKey:NSLocalizedDescriptionKey];
     if (err != nil) *err = [NSError errorWithDomain:EDStringDomain code:EDEmptyStringError userInfo:errorInfo];
     return NO;
   }
   if (somethingElseIsWrongWithString) {
     DLog(@"Another Problem Geesh");
     NSDictionary *errorInfo = [NSDictionary dictionaryWithObject:EDAnotherStringErrorDescription forKey:NSLocalizedDescriptionKey];
     if (err != nil) *err = [NSError errorWithDomain:EDStringDomain code:EDAnotherStringError userInfo:errorInfo];
     return NO;
   }
}

Now whichever error hits is being properly established and displayed in the popup as expected the first time through. The problem comes in when the user clicks on something that activates either the 'mainMethod' again or another method that calls 'parseAndStoreString:error:' (there are three or four that call the method). If there is another error, the popup is showing the description for the first error and the second error glued together into one string. This is ARC code, so my understanding is that the compiler should be releasing the myError object (or whatever NSError object the other methods are creating) after the error is presented. I don't think the problem is in the 'popupWithErrorMessage' method since I only pass in a copy of the localized description which gets displayed and then destroyed by [popupView orderOut:self]. Any ideas on how the heck these error messages keep piling up in the NSError object?

@torrey.lyons : Sure, here is the code for togglePopupWithMessage:onView-

- (void)popupWithErrorMessage:(NSString *)errorToDisplay {
   if (!messagePopup) {
      if (errorToDisplay == nil) {
         DLog(@"Warning, incoming error message was nil");
         return;
      }

      NSDictionary *messageAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                     [NSColor whiteColor], NSForegroundColorAttributeName,
                                     [NSFont systemFontOfSize:12], NSFontAttributeName,
                                     nil];
      NSAttributedString *messageWithAttributes = [[NSAttributedString alloc]
                                                  initWithString:errorToDisplay
                                                  attributes:messageAttributes];

      NSPoint messagePoint = NSMakePoint(NSMidX([[self.mainSplitView.subviews objectAtIndex:1] frame]),
                                        NSMinY([anchorView frame])+4.0f);
      messagePopup = [[MAAttachedWindow alloc] initWithView:popupView 
                                            attachedToPoint:messagePoint 
                                                   inWindow:[self window]
                                                     onSide:MAPositionBottom 
                                                 atDistance:0];
      [messagePopup setAlphaValue:0.0f];

      NSTextStorage *messageStorage = popupMessage.textStorage;
      [messageStorage beginEditing];
      [messageStorage insertAttributedString:messageWithAttributes atIndex:0];
      [messageStorage endEditing];

      [messagePopup setFrame:NSMakeRect(messagePopup.frame.origin.x, messagePopup.frame.origin.y, 250.0f, 100.0f)
                   display:YES];

      messageWithAttributes = nil;
      messageAttributes = nil;
      errorToDisplay = @"";

      [[self window] addChildWindow:messagePopup ordered:NSWindowAbove];


      [[messagePopup animator] setAlphaValue:1.0f];
      [popupMessage setNeedsDisplay:YES];

      [NSTimer scheduledTimerWithTimeInterval:3.5
                                       target:self
                                     selector:@selector(turnOffPopupFromTimer:)
                                     userInfo:nil
                                      repeats:NO];
   } else {
      [[self window] removeChildWindow:messagePopup];
      [messagePopup fadeOutAndOrderOut:YES];
      messagePopup = nil;
   }
- (void)turnOffPopupFromTimer:(NSTimer *)timer {
   if (messagePopup) {              
                                    //Added to correct problem \/\/\/\/
      NSTextStorage *messageStorage = popupMessage.textStorage;
      [messageStorage beginEditing];
      [messageStorage deleteCharactersInRange:NSMakeRange(0, messageStorage.characters.count)];
      [messageStorage endEditing];  
                                    //Added to correct problem /\/\/\/\
      [[self window] removeChildWindow:messagePopup];
      [messagePopup fadeOutAndOrderOut:YES];
      messagePopup = nil;
   }
}

Upvotes: 0

Views: 245

Answers (1)

torrey.lyons
torrey.lyons

Reputation: 5589

I suspect the problem is in popupWithErrorMessage, which is piling up the localized descriptions. Even if there is a bug in the lifecycle of your NSError objects, each one created for a separate error is a separate object and won't have the localized description of other NSError objects stuffed into it. On the other hand, your description of popupWithErrorMessage sounds suspicious: [popupView orderOut:self] just removes the window from the screen but does not release it or cause it to be destroyed. Can you post the code for popupWithErrorMessage?

Upvotes: 1

Related Questions