title: Asynchronously loading sound resources in viewDidLoad crashes
body: <p>All,</p>
  
  <p>I am attempting to load a set of sounds asynchronously when I load a UIViewController. At about the same time, I am (occasionally) also placing a UIView on the top of my ViewController's hierarchy to present a help overlay. When I do this, the app crashes with a bad exec. If the view is not added, the app does not crash. My ViewController looks something like this:</p>
  
  <pre><code>- (void)viewDidLoad
  {
      [super viewDidLoad];
  
      __soundHelper = [[SoundHelper alloc] initWithSounds];
  
      // Other stuff
  }
  
  - (void)viewDidAppear:(BOOL)animated
      {
      // ****** Set up the Help Screen
      self.coachMarkView = [[FHSCoachMarkView alloc] initWithImageName:@"help_GradingVC" 
                                                      coveringView:self.view 
                                                       withOpacity:0.9 
                                                      dismissOnTap:YES 
                                                      withDelegate:self];
  
      [self.coachMarkView showCoachMarkView];
      [super viewDidAppear:animated];
  }
  </code></pre>
  
  <p>The main asynchronous loading method of <code>SoundHelper</code> (called from 'initWithSounds') looks like this:</p>
  
  <pre><code>// Helper method that loads sounds as needed
  - (void)loadSounds {
  
      // Run this loading code in a separate thread
      NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
      NSBlockOperation *loadSoundsOp = [NSBlockOperation blockOperationWithBlock:^{
          // Find all sound files (*.caf) in resource bundles
          __soundCache = [[NSMutableDictionary alloc]initWithCapacity:0];
  
          NSString * sndFileName;
          NSArray *soundFiles = [[NSBundle mainBundle] pathsForResourcesOfType:STR_SOUND_EXT inDirectory:nil];
  
          // Loop through all of the sounds found
          for (NSString * soundFileNamePath in soundFiles) {
              // Add the sound file to the dictionary
              sndFileName = [[soundFileNamePath lastPathComponent] lowercaseString];
              [__soundCache setObject:[self soundPath:soundFileNamePath] forKey:sndFileName];
          }
  
          // From: https://stackoverflow.com/questions/7334647/nsoperationqueue-and-uitableview-release-is-crashing-my-app
          [self performSelectorOnMainThread:@selector(description) withObject:nil waitUntilDone:NO];
      }];
      [operationQueue addOperation:loadSoundsOp];
  }
  </code></pre>
  
  <p>The crash seems to occur when the block exits. The <code>init</code> of <code>FHSCoachMarkView</code> looks like this:</p>
  
  <pre><code>- (FHSCoachMarkView *)initWithImageName:(NSString *) imageName 
                             coveringView:(UIView *) view
                              withOpacity:(CGFloat) opacity
                             dismissOnTap:(BOOL) dismissOnTap
                             withDelegate:(id&lt;FHSCoachMarkViewDelegate&gt;) delegateID
  {
      // Reset Viewed Coach Marks if User Setting is set to show them
      [self resetSettings];
  
      __coveringView = view;        
      self = [super initWithFrame:__coveringView.frame];
      if (self) {
          // Record the string for later reference
          __coachMarkName = [NSString stringWithString:imageName];
          self.delegate = delegateID;
  
          UIImage * image = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:imageName ofType:@"png"]];
  
          // ****** Configure the View Hierarchy
          UIImageView *imgView = [[UIImageView alloc] initWithImage:image];
  
          [self addSubview:imgView];
          [__coveringView.superview insertSubview:self aboveSubview:__coveringView];
  
          // ****** Configure the View Hierarchy with the proper opacity
          __coachMarkViewOpacity = opacity;
          self.hidden = YES;
          self.opaque = NO;
          self.alpha = __coachMarkViewOpacity;
  
          imgView.hidden = NO;
          imgView.opaque = NO;
          imgView.alpha = __coachMarkViewOpacity;
  
          // ****** Configure whether the coachMark can be dismissed when it's body is tapped
          __dismissOnTap = dismissOnTap;
  
          // If it is dismissable, set up a gesture recognizer
          if (__dismissOnTap) {
              UITapGestureRecognizer * tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self 
                                                                                        action:@selector(coachMarkWasTapped:)];
              [self addGestureRecognizer:tapGesture];
          }
      }
      return self;
  }
  </code></pre>
  
  <p>I have tried invoking the asynchronous block using both <code>NSBlockOperation</code> and <code>dispatch_async</code> and both have had the same results. Additionally, I've removed the aysnch call altogether and loaded the sounds on the main thread. That works fine. I also tried the solution suggested by @Jason in: <a href="https://stackoverflow.com/questions/7334647/nsoperationqueue-and-uitableview-release-is-crashing-my-app">NSOperationQueue and UITableView release is crashing my app</a> but the same thing happened there too.</p>
  
  <p>Is this actually an issue with the view being added in FHSCoachMarkView, or is it possibly related to the fact that both access <code>mainBundle</code>? I'm a bit new to asynch coding in iOS, so I'm at a bit of a loss. Any help would be appreciated!</p>
  
  <p>Thanks,
  Scott</p>