Douglas
Douglas

Reputation: 153

UIImage loaded from NSData displays black only on new iPad 3

I have a universal binary app that is currently published in iTunes and works correctly on iPhone 3, 4, 4S, iPad 2 on iOS 4.x through 5.1, but displays a black UIImage on the new iPad (3) running iOS 5.1.

Has anyone else encountered this? Any fix suggestions?

The problem is that a UIImage loaded from NSData displays as black.

I initially thought the NSData may be nil or unreadable, so I added UIAlert & NSLog to output the NSData length and the UIImage size properties (assuming that reading the data successfully into UIImage would produce reasonable size values). Everything looks OK in the UIAlert...

// MyView.m

- (NSData*)getImageData

{      

     Screening *screen = [[Model sharedInstance] screenInProgress];

     return screen.anteriorImage;  // returns the NSData from the managed 'Screening' object

}


- (void)viewWillAppear:(BOOL)animated

{
     NSData *imagedata = [self getImageData];

     UIImage *image = [UIImage imageWithData:imagedata];

     [clientImageView setImage:image];     /// UIImageView in nib




     /// apply user grid
     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];


     if ([defaults integerForKey:@"com.ikonetics.posture.gridoverlay"] >= 0) {     

          UIImageView *grid = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"grid.png"]];

          [grid setBackgroundColor:[UIColor clearColor]];

          [grid setAlpha:0.6f];

          [grid setFrame:clientImageView.frame];

          [screenshotWrapper addSubview:grid];     // screenshotWrapper is a UIView in xib arranged as a parent to other views

          [grid release];

     }


     NSString *note = [NSString 

                           stringWithFormat:@"NSData length: %d \nUIImage size: %@ \nUIImage scale: %1.f \nClientImage info: %@"

                           , [imagedata length]

                           , NSStringFromCGSize(image.size)

                           , image.scale

                           , [clientImageView description]

                           ];



     NSLog(@"debug note: %@ ", note);

     UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"DEBUG INFO" 

                                                                 message:note

                                                               delegate:nil

                                                    cancelButtonTitle:@"OK"

                                                    otherButtonTitles:nil];

     [alert show];   

     [alert release];



}



// Screening.h

@interface Screening : NSManagedObject


@property (nonatomic, retain) NSData * anteriorImage;     // this data is stored elsewhere using UIImageJPEGRepresentation(image, 0.8);
...
@end

Screenshot from an iPad 3 showing the UIAlertView, you can see that the NSData has length and the UIImage has size and the UIImageView (ClientImage) has reasonable frame, and the grid overlay UIImage shows correctly, as expected.

iPad 3 screenshot

Finally, this has been tested with the /// apply user grid option disabled as well, so the overlay png is not even instantiated as that code block does not run. The black UIImage problem persists.

Anyone else having issues with a UIImageView showing a black UIImage instead of the actual image? Any thoughts or ideas on how to fix the code so this works correctly on the iPad 3?

Thanks!

EDIT - More debugging information:

I wrote the NSData (imagedata) out to an email so I could view it off the device. I wanted to find out if perhaps the image itself was blank / black and learned that the data displays correctly as an image when saved off the device (it is not blank).

So, the NSData loaded into the UIImage & UIImageView shows black... but when attached to an email it shows the image correctly.

Further, I wanted to make sure the hierarchy of views is showing as intended; check that my image is not underneath another view. Starting from the ViewController's view, I logged the recursiveDescription and learned that the hierarchy of views on the iPad 3 matches the iPad 2, and is exactly how I would expect it.

New debugging code:

NSString *note = [NSString 
                  stringWithFormat:@"NSData length: %d \nUIImage size: %@ \nUIImage scale: %1.f \nRecursive info: %@"
                  , [imagedata length]
                  , NSStringFromCGSize(image.size)
                  , image.scale
                  , [[self view] recursiveDescription]
                  ];

MFMailComposeViewController *mailViewController = [[MFMailComposeViewController alloc] init];
mailViewController.mailComposeDelegate = self;
[mailViewController setSubject:@"Debug email"];
[mailViewController setMessageBody:note isHTML:NO];
[mailViewController addAttachmentData:imagedata mimeType:@"image/jpg" fileName:@"imagedata.jpg"];

[self presentModalViewController:mailViewController animated:YES];
[mailViewController release];

Finally, here is the recursive log info from both 2 & 3 devices:

iPad 2 log:

NSData length: 123254 
UIImage size: {800, 960} 
UIImage scale: 1 
Recursive info: <UIView: 0x10a91620; frame = (0 0; 768 960); autoresize = W+H; layer = <CALayer: 0x10a91650>>
   | <UIScrollView: 0x10a90a10; frame = (0 0; 768 960); clipsToBounds = YES; autoresize = RM+TM; layer = <CALayer: 0x10a90bb0>; contentOffset: {0, 0}>
   |    | <UIView: 0x10a90be0; frame = (0 0; 1536 1920); autoresize = LM+RM+TM+BM; layer = <CALayer: 0x10a90c10>>
   |    |    | <UIView: 0x10a90c40; frame = (384 480; 768 960); autoresize = LM+RM+TM+BM; layer = <CALayer: 0x10a90c70>>
   |    |    |    | <UIImageView: 0x10a908f0; frame = (0 0; 768 960); opaque = NO; autoresize = LM+RM+TM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x10a90930>>
   |    |    |    | <LineView_iPad: 0x10a90ce0; frame = (0 0; 768 960); autoresize = LM+RM+TM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x10a90d20>>
   |    |    |    | <PointView_iPad: 0x10a90dd0; frame = (0 0; 768 960); autoresize = LM+RM+TM+BM; layer = <CALayer: 0x10a90e20>>
   |    |    |    | <UIImageView: 0x10a96480; frame = (0 0; 768 960); alpha = 0.6; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x10a966e0>>
   | <UIView: 0x10a91680; frame = (-10 750; 220 220); autoresize = RM+TM; layer = <CALayer: 0x10a916b0>>
   |    | <UIImageView: 0x10a916e0; frame = (0 0; 220 220); autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x10a91720>>
   |    | <UIImageView: 0x10a91480; frame = (10 10; 200 200); autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x10a914c0>>
   |    | <UIImageView: 0x10a91840; frame = (102 102; 16 16); autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x10a91880>>

iPad 3 log:

NSData length: 166252
UIImage size: {784, 980}
UIImage scale: 1
Recursive info: <UIView: 0xc669470; frame = (0 0; 768 980); autoresize = W+H; layer = <CALayer: 0xc667550>>
 | <UIScrollView: 0x33d410; frame = (0 20; 768 960); clipsToBounds = YES; autoresize = RM+TM; layer = <CALayer: 0x325840>; contentOffset: {0, 0}>
 |    | <UIView: 0x308630; frame = (0 0; 1536 1920); autoresize = LM+RM+TM+BM; layer = <CALayer: 0xc666f40>>
 |    |    | <UIView: 0x318970; frame = (384 480; 768 960); autoresize = LM+RM+TM+BM; layer = <CALayer: 0xc682a70>>
 |    |    |    | <UIImageView: 0xc66cd60; frame = (0 0; 768 960); opaque = NO; autoresize = LM+RM+TM+BM; userInteractionEnabled = NO; layer = <CALayer: 0xc672c00>>
 |    |    |    | <LineView_iPad: 0x301680; frame = (0 0; 768 960); autoresize = LM+RM+TM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x329fa0>>
 |    |    |    | <PointView_iPad: 0xc6841b0; frame = (0 0; 768 960); autoresize = LM+RM+TM+BM; layer = <CALayer: 0xc672b10>>
 |    |    |    | <UIImageView: 0xc588b70; frame = (0 0; 768 960); alpha = 0.6; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0xc589500>>
 | <UIView: 0x324330; frame = (-10 770; 220 220); autoresize = RM+TM; layer = <CALayer: 0xc687970>>
 |    | <UIImageView: 0xc665b80; frame = (0 0; 220 220); autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x321490>>
 |    | <UIImageView: 0x314e50; frame = (10 10; 200 200); autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0xc684f30>>
 |    | <UIImageView: 0x63d220; frame = (102 102; 16 16); autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0xc580d90>>

Despite this post being so unbearably long, I do hope someone out there can think of anything that may cause this issue...

Upvotes: 3

Views: 1844

Answers (1)

Douglas
Douglas

Reputation: 153

This appears to be a bug with iOS. This is the workaround:

  • In Interface Builder change the UIImageView background texture to any color

That's it.

I stumbled across this during debugging while arbitrarily flipping switches trying to get something interesting to happen. My code / app is not using the background color of the UIImageView, its property has not been adjusted... ever?

In my code above, the UIImageView 'clientImageView' had its background set with texture "View Flipside Background Color". With that texture set as the background the loaded UIImage refused to display. Changing the background texture to anything but Flipside, and the UIImage displayed as expected.

  • The ONLY change we made was to the background color property of the UIImageView within the Interface Builder.
  • The ONLY place the error appeared was on the iPad 3 hardware running iOS 5.1.
  • It fails every time and is reproducible
  • also tested on Phone 4, 4S, iPad 2 on iOS 4.x through 5.1

Reported to Apple as Bug ID# 11080928

Upvotes: 2

Related Questions