title: objective c memory leak ARC with UIImage
body: <p>Leaks tool is complaining a memory leak in UIImage of a class method. How to solve this one?
  <img src="https://i.stack.imgur.com/2uyTJ.png" alt="enter image description here"></p>
  
  <p>Here are the functions that cause the memory leak. The places where the leaks are occurring are shown by "memory leak occurs here.: comment<br></p>
  
  <p>1<br>`+(UIImage *) bubbleWithImage: (UIImage *) bubbleImage withColor: (UIColor *) color {</p>
  
  <pre><code>// Get a CGImageRef so we can use CoreGraphics
  CGImageRef image = bubbleImage.CGImage;
  
  CGFloat width = CGImageGetWidth(image);
  CGFloat height = CGImageGetHeight(image);
  
  // Create a new bitmap context i.e. a buffer to store the pixel data
  CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
  
  size_t bitsPerComponent = 8;
  size_t bytesPerPixel    = 4;
  size_t bytesPerRow      = (width * bitsPerComponent * bytesPerPixel + 7) / 8; // As per the header file for CGBitmapContextCreate
  size_t dataSize         = bytesPerRow * height;
  
  // Allocate some memory to store the pixels
  unsigned char *data = malloc(dataSize);
  memset(data, 0, dataSize);
  
  // Create the context
  CGContextRef context = CGBitmapContextCreate(data, width, height,
                                               bitsPerComponent, bytesPerRow, colorSpace,
                                               kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
  
  CGColorSpaceRelease(colorSpace);
  
  // Draw the image onto the context
  CGContextDrawImage(context, CGRectMake(0, 0, width, height), image);
  
  // Get the components of our input color
  const CGFloat * colors = CGColorGetComponents(color.CGColor);
  
  // Change the pixels which have alpha &gt; 0 to our new color
  for (int i  = 0 ; i &lt; width * height * 4 ; i+=4)
  {
      // If alpha is not zero
      if (data[i+3] != 0) {
          data[i] = (char) (colors[0] * 255);
          data[i + 1] = (char) (colors[1] * 255);
          data[i + 2] = (char) (colors[2] * 255);
      }
  }
  
  // Write from the context to our new image
  // Make sur to copy across the orientation and scale so the bubbles render
  // properly on a retina screen
  //****memory leak occurs here.
  UIImage * newImage = [[UIImage imageWithCGImage:CGBitmapContextCreateImage(context)
                                            scale:bubbleImage.scale
                                      orientation:bubbleImage.imageOrientation] stretchableImageWithLeftCapWidth:bubbleImage.leftCapWidth
                                                                                                           topCapHeight:bubbleImage.topCapHeight];
  // Free up the memory we used
  CGContextRelease(context);
  free(data);
  //CGImageRelease(image);
  
  return newImage;
  </code></pre>
  
  <p>}
  `
  <br>2<br></p>
  
  <pre><code>-(void) setMessage: (id&lt;PMessage, PMessageLayout&gt;) message {
  // Set the message for later use
  _message = message;
  
  // Update the image
  UIImage * image = (message.isMine) ? _meBubbleImage : _replyBubbleImage;
  
  // Set the bubble to be the correct color
  if (message.color || [message.color isEqualToString:@""]) {
      message.color = @"0.098039 0.784313 0.674509 1";
  }
  //**memory leak occurs here.
  bubbleImageView.image = [BMessageCell bubbleWithImage:image withColor:[BMessage stringToColor:message.color]];
  /*
   * default colour is 0.098039 0.784313 0.674509 1
   * sender colour is  0.741176 0.941176 0.909803 1
   * light green   is  0.925490 0.976470 0.784313 1
   */
  //build1.5 [check sender]
  if (message.isMine) {
      bubbleImageView.image = [BMessageCell bubbleWithImage:image withColor:[BMessage stringToColor:@"0.925490 0.976470 0.784313 1"]];
  }else{
      bubbleImageView.image = [BMessageCell bubbleWithImage:image withColor:[BMessage stringToColor:@"0.741176 0.941176 0.909803 1"]];
  }
  
  // If the image has an image URL
  _profilePicture.hidden = YES;
  //[[AsyncImageLoader sharedLoader] cancelLoadingImagesForTarget:_profilePicture];
  
  if (message.user) {
      _profilePicture.hidden = NO;
      _profilePicture.image = message.user.picture;
      NSString *imageURL = [BThreadsViewController getUserImageForEmail:message.user.email];
      ProfilePicManager *mgr = [ProfilePicManager getProfilePicManagerInstance];
      UIImage *savedImage = [mgr retrieveFromDictionary:imageURL];
      if (savedImage) {
          _profilePicture.image = savedImage;
      } else {
          //dwonload the image asyncronously
          [[[AsyncImageDownloader alloc] initWithMediaURL:imageURL successBlock:^(UIImage *image)  {
              _profilePicture.image = image;
              [mgr addToDictionary:imageURL image:image];
          } failBlock:^(NSError *error) {
              NSLog(@"Failed to download image due to %@!", error);
          }] startDownload];
      }
  }
  
  NSDateFormatter * dateFormatter = [[NSDateFormatter alloc] init];
  
  NSTimeInterval interval = fabsf([_message.date timeIntervalSinceNow]);
  // More than a day ago
  if (interval &gt; 3600 * 24) {
      // More than a year ago
      if (interval &gt; 3600 * 24 * 365) {
          [dateFormatter setDateFormat:@"MM/yy"];
      }
      else {
          [dateFormatter setDateFormat:@"dd MMM"];
      }
  }
  else {
      [dateFormatter setDateFormat:@"HH:mm"];
  }
  
  // Add the correct date
  _timeLabel.text = [dateFormatter stringFromDate:_message.date];;
  </code></pre>
  
  <p>}
  <br>3<br></p>
  
  <pre><code>-(void) setMessage: (id&lt;PMessage, PMessageLayout&gt;) message {
  //**memory leak occurs here.
  [super setMessage:message];
  
  textView.text = message.text;
  textView.font = [BMessage fontWithName:message.fontName size:message.fontSize.floatValue];
  @try {
      //textView.textColor = [UIColor colorWithCGColor:newcolor.CGColor];
      textView.textColor = [BMessage stringToColor:message.textColor];
  }
  @catch (NSException *exception) {
      textView.textColor = [UIColor blackColor];
  }
  </code></pre>
  
  <p>}
  <br>4<br></p>
  
  <pre><code>- (UITableViewCell *)tableView:(UITableView *)tableView_ cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  id&lt;PMessage, PMessageLayout&gt; message;
  if (indexPath.row &lt; [self messages].count) {
      message = [self messages][indexPath.row];
  } else {
      message = NULL;
  }
  
  UITableViewCell&lt;BMessageDelegate&gt; * messageCell;
  if (message) {
      if (message.type.intValue == bMessageTypeText) {
          messageCell = [tableView_ dequeueReusableCellWithIdentifier:bTextMessageCell];
      }
      else if (message.type.intValue == bMessageTypeImage) {
          messageCell = [tableView_ dequeueReusableCellWithIdentifier:bImageMessageCell];
      }
      else if (message.type.intValue == bMessageTypeLocation) {
          messageCell = [tableView_ dequeueReusableCellWithIdentifier:bLocationCell];
      }
      else if (message.type.intValue == bMessageTypeAudio) {
          messageCell = [tableView_ dequeueReusableCellWithIdentifier:bAudioMessageCell];
          if ([messageCell isKindOfClass:[BAudioMessageCell class]]) {
              BAudioMessageCell *audioCell = (BAudioMessageCell*)messageCell;
              //build1.5 [set prg color]
              [audioCell.progressView setTintColor:[UIColor redColor]];
              [audioCell.progressView setBackgroundColor:[UIColor whiteColor]];
  
  
              audioCell.delegate = self;
          } else {
              messageCell = [[BAudioMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:bAudioMessageCell];
              BAudioMessageCell *audioCell = (BAudioMessageCell*)messageCell;
              //build1.5 [set prg color]
              [audioCell.progressView setTintColor:[UIColor redColor]];
              [audioCell.progressView setBackgroundColor:[UIColor whiteColor]];
  
          }
      }
      [((id&lt;BMessageDelegate&gt;)messageCell) makeDiliveredButtonVisible];
  } else {
      NSString *CellIdentifier = NULL;
      if (isUpLoadingAudio) {
          CellIdentifier = @"dummyCellAudio";
      } else if(isUpLoadingImage){
          CellIdentifier = @"dummyCellImage";
      }
  
      UITableViewCell&lt;DummyView&gt; *cell = NULL;
      if (isUpLoadingImage) {
          cell = [[ImageDummyCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
      } else if (isUpLoadingAudio) {
          cell = [tableView_ dequeueReusableCellWithIdentifier:CellIdentifier];
          if (cell == nil) {
              cell = [[AudioDummyCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
          }
      }
      [(((id&lt;DummyView&gt;)cell)) configureMsgCell];
      uploadProgressView = [((id&lt;DummyView&gt;)cell) uPView];
  
      return cell;
  }
  
  if (indexPath.row &lt; [self messages].count) {
      //**memory leak occurs here.
      [messageCell setMessage:message];
  }
  NSLog(@"row %d",indexPath.row);
  
  return messageCell;
  </code></pre>
  
  <p>}</p>