title: CGImage/UIImage passing causes EXE-BAD-ACCESS
body: <p><strong>FIXED: I'm not sure yet why. Code has been updated below, and notes at the bottom</strong></p>
  
  <p>I'm having a very strange error that does not show up on the Simulator (even when running Instruments), unless I turn on all the Zombie and Debug options.  However, it will crash the phone after a minute of updates (1 update per second).  I have a 2D array that I take a subset of, apply a colormap, and turn into an image (this array changes constantly).  Then I pass that image to the model, and the viewcontroller grabs it from the model once it receives notification of an update.  I'll layout the 3 classes -Spectrogram, Model, ViewController:</p>
  
  <p>Here are the important bits of each (there is more, but not relevant):</p>
  
  <p>Spectrogram.h  (Sorry, I can't get this to indent correctly on here)</p>
  
  <pre><code>@interface: Spectrogram : NSObject
  {
      NSMutableData *arrayData;
  }
  //renamed so Xcode allows the object with +1 reference count to be returned
  - (CGImageRef)newSpectrogramImage;  
  </code></pre>
  
  <p>Spectrogram.m</p>
  
  <pre><code>@implementation Spectrogram
  - (CGImageRef)newSpectrogramImage
  {
      //slightly reordered
      NSMutableData *imageData = [[NSMutableData alloc] init];
      ...code to go through arrayData and colormap it (get RGB transform) and store in imageData...
      CGImageRef arrayImage = nil;
      CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
      //specifically tell CGImage there is no alpha channel
      CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaNone;
      //Use the toll-free bridge between NSData and CFData
      CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)imageData);
      arrayImage = CGImageCreate((slices-startSlice), bins, 8, 24, 3*(slices-startSlice), colorSpace, bitmapInfo, provider, NULL, false, kCGRenderingIntentDefault);  //image is rotated now, so width and height are switched
      CGColorSpaceRelease(colorSpace);
      CGDataProviderRelease(provider);
      CGImageRelease(arrayImage);
      [imageData release];
      //Pass the CGImageRef with a reference count of 1
      return arrayImage;
  }
  </code></pre>
  
  <p>Model.h</p>
  
  <pre><code>@interface: Model : NSManagedObject
  {
      Spectrogram *spectrogram;
  }
  //Function the viewController can call to get the update
  - (CGImageRef)newSpectrogramImage;  
  </code></pre>
  
  <p>Model.m</p>
  
  <pre><code>@implementation Model
  ... there is a function that adds new data to the array and notifies all listeners...
  - (CGImageRef)newSpectrogramImage {
      return [spectrogram newSpectrogramImage];
  }
  </code></pre>
  
  <p>ViewController.h</p>
  
  <pre><code>@interface: ViewController : UIViewController 
  { 
  }
  //the root controller actually alloc's the record, and sets this property when creating this view
  @property (nonatomic, retain) Record *currentRecord;  
  </code></pre>
  
  <p>ViewController.m</p>
  
  <pre><code>@implementation ViewController
  @synthesize spectrogramView;
  - (void)viewDidLoad
  {
      [super viewDidLoad];
      [[NSNotificationCenter ... listen for model updates...
  }
  
  //now, the real meat
  - (void)recordUpdated:(NSNotification*)notification
  {
      CALayer *myLayer = self.view.layer;
      CGImageRef spectrogramImage = nil;
      spectrogramImage = [currentRecord newSpectrogramImage];
      myLayer.contents = (id)spectrogramImage;
      CGImageRelease(spectrogramImage); 
  }
  </code></pre>
  
  <p>I've changed this so many times in the last day trying to hunt down where and why it fails.  I've tried passing the CGImageRef instead (but since that isn't an object, I'm worried about making copies of what can be a -huge- image) and it still fails.  And it works perfectly in the simulator (will run for dozens of minutes).  But fails within a minute on the iphone, or if I turn on the debug options for the simulator (it will fail as soon as the viewcontroller is loaded).</p>
  
  <p>On a side note, that might be of some use.  This viewcontroller is loaded as a modal view when the phone is turned sideways (works great).  However, I have a lot of NSLogs in there and I see this viewcontroller's dealloc is called before the mainviewcontroller even gets to viewwilldisappear - but it still runs.  And then this controller's dealloc is called again when the phone is turned back and the view disappears.</p>
  
  <p><strong>Note</strong>
  The version that worked well in the simulator passed CGImageRefs all the way to the viewController, instead of UIImages.  I've tried at least 50 different combinations of where to create the UIImage from the CGImage, and what's posted above is just one of them (all of them fail eventually, or immediately).  Of note, with the code above, if I do add this to the viewController modelUpdated:</p>
  
  <pre><code>CGSize size = currentModel.spectrogramImage.size;
  NSLog(@"width: %f", size.width);
  </code></pre>
  
  <p>and comment out assigning it to the spectrogramView, the width is reported correctly, so the UIImage is getting passed along, it's just not getting retained (This is how I understand the EXE_BAD_ACCESS error).</p>
  
  <p>Also, recently I receive dan EXE_BAD_ACCESS on the </p>
  
  <pre><code>self.spectrogramImage = [spectrogram getSpectrogramImage];
  </code></pre>
  
  <p>line.  So, I think the error may be inside the Spectrogram class.  Even though the CGImage and UIImage code was taken from Apple examples.</p>
  
  <p><strong>Fixed notes</strong>
  I read that setting the contents of the CALayer was a much quicker way to pass a CGImageRef to a view - and no UIImage intermediary.  Unfortunately, I only commit working changes, so I can't see every iteration I went through.  However, I know that I had something very similar to this several times that kept crashing.  The problem was always that as it is currently written, the program would crash with EXE_BAD_ACCESS.  And if I upped the reference count (or didn't release it), then it would work perfectly, but the object would leak.  I still don't understand how that is possible.  To have the difference between a leak, and a BAD ACCESS be a reference count of 1 (and not 2 or more).</p>