简体   繁体   中英

iOS 6 MFMailComposeViewController: Only support RGBA or the White color space, this method is a hack

really, really odd error

I have an app that was working fine in iOS5/.1, now I'm having a few transition problems with iOS6 but this one is confusing.

I have some code that launches a mail composer, and since iOS 6 it causes a crash with this error:

* Assertion failure in -[UICGColor encodeWithCoder:], /SourceCache/UIKit/UIKit-2372/UIColor.m:1191 2012-09-26 02:14:38.044 MyCQs Medical[2126:1b03] * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Only support RGBA or the White color space, this method is a hack.'

Any suggestions? Through trial and error commenting out various lines it seems to be the alloc/init line that causes the error, though when all the lines are uncommented, all of the NSLogs are executed, including "present" which indicates that everything that should be called, has been. the app crashes before the mailcomposer is presented on screen, I'd really appreciate any advice here

            if (indexPath.row == 3) {
               if([MFMailComposeViewController canSendMail]){
                   mailComposer = [[MFMailComposeViewController alloc]init];
                   NSLog(@"Alloc, init");
                   mailComposer.mailComposeDelegate = self;
                   NSLog(@"Set delegate");
                   NSArray *toArray = [[NSArray alloc]initWithObjects:@"john@doe.com", nil];
                   NSLog(@"To array");
                   [mailComposer setToRecipients:toArray];
                   NSLog(@"To recipients");
                   [mailComposer setSubject:@"Message from a MyCQs user!"];
                   NSLog(@"Subject");
                   NSLog(@"About to present mail composer");
                   [[mailComposer navigationBar] setTintColor:[UIColor blackColor]];
                   [self presentModalViewController:mailComposer animated:YES];
                   NSLog(@"Present");
             }
    }

Ok only a partial solution but it's the best one I can think of without some fairly disruptive code changes.

For anyone else who gets this problem in future, I think it's a bug in iOS 6, MFMailComposeViewController crashes when you have set the UITableView separatorStyle to a colorWithPatternImage, but it works fine when you use a solid colour, so:

        if ([[[UIDevice currentDevice] systemVersion] floatValue] > 5.2) {
           NSLog(@"Using iOS 5x");
           [[UITableView appearance]setSeparatorColor:[UIColor colorWithRed:142.0/255.0          green:130.0/255.0 blue:76.0/255.0 alpha:1.0]];
        }
        else {
           NSLog(@"Using iOS 6x, Table view use pattern color");
           [[UITableView appearance]setSeparatorColor:[UIColor colorWithPatternImage: [UIImage imageNamed:@"dotted-line2.png"]]];
        }

Actually I believe this is a significant bug, did anybody file a radar, yet?

As it seems to me, the assertion throws whenever you use "colorWithPatternImage" ANYWHERE in your presenting view controller's appearance proxies.

I think what happens is that iOS tries to store the appearance of your App before switching to a separate service (which is what MFMailComposeViewController does, it's now a "remote view controller" that gets presented by your App but which is managed by another App/process), since the Mail App wants to determine the appearance itself so it changes things like tint colors etc. More about remote view controller here, in case somebody is interested: http://oleb.net/blog/2012/10/remote-view-controllers-in-ios-6/

This seems to fail. This has to be a bug, the image should be encodable.

Workarounds may be hard. I tried to exchange the patterned color for a plain one right before presenting the view controller but found you at least have to make sure it really gets redrawn on screen and gave up (I don't really needed the pattern).

我的问题也是由于使用了colorWithPatternImage,但我发现它似乎只会在MFMailCompserViewController上显示的元素上使用时产生问题,例如:

[[UINavigationBar appearance] setTintColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"navbar"]]];

I've found that MFMailComposeViewController only crashes when colorWithPatternImage is used in [[UITableView appearance] statement. I've had no problem when I set the background and separatorColor in the table's viewDidLoad. The only problem is you need to do this for each table.

[self.tableView setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"image.png"]]];
[self.tableView setSeparatorColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"image.png"]]];

@coolio is right, it seems to happen when using a patterned color with any controller class. (At least UITabBarController and UITableViewController, apparently.)

I got around this by subclassing my tab bar controller and using appearanceWhenContainedIn:. That way you can still use your fancy texture with no need to subclass MFMailComposeViewController or sniff iOS versions, etc.

UIColor *tabBarBgPattern = [UIColor colorWithPatternImage:...];
[[UITabBar appearanceWhenContainedIn:[MyTabBarController class],
                                     nil]
                  setBackgroundColor:tabBarBgPattern];

This thread gave me great clues on how to fix a similar problem in my App using ShareKit and attempting to email an image of a view. Now I only change the UISwitch appearance for versions less than 6.0.

This code gets called when my app starts up:

// Protect against IOS 6.0 BUG: 'NSInternalInconsistencyException', reason: 'Only support RGBA or the White color space, this method is a hack.'
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 6.0) {
    UIImage *patternImage = [UIImage imageNamed:@"solid-colors_blue.png"];
    UIColor* switchColor = [UIColor colorWithPatternImage:patternImage];
    [[UISwitch appearance] setOnTintColor: switchColor];
}  

I'm facing the same issue using 'colorWithPatterImage' for a UIBarButtonItem inside the navBar of my tableViewController used to display the a modal view (I'm not using MFMailComposeViewController ).

[[UIBarButtonItem appearance] setTintColor:[UIColor colorWithPatternImage:bgImage]];

I needed to replace it with a RGBa color;

My apps were crashing on iOS 7 when using colorWithPatternImage and trying to present an MFMailComposeViewController . I have to determine the color from a UIImage because the UIImage can be chosen by the user, and I want to "theme" my application based on the user's selected image.

The solution for me (albeit kind of hacky) is to grab the RGBA values of the origin (0,0) of the UIImage, then apply that as the background color instead of using colorWithPatternImage .

+ (UIColor*)getUIColorFromImageAtOrigin:(UIImage*)image
{        
    // First get the image into your data buffer
    CGImageRef imageRef = [image CGImage];
    NSUInteger width = CGImageGetWidth(imageRef);
    NSUInteger height = CGImageGetHeight(imageRef);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    unsigned char *rawData = (unsigned char*) calloc(height * width * 4, sizeof(unsigned char));
    NSUInteger bytesPerPixel = 4;
    NSUInteger bytesPerRow = bytesPerPixel * width;
    NSUInteger bitsPerComponent = 8;
    CGContextRef context = CGBitmapContextCreate(rawData, width, height,
                                                 bitsPerComponent, bytesPerRow, colorSpace,
                                                 kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGColorSpaceRelease(colorSpace);

    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
    CGContextRelease(context);

    // Now your rawData contains the image data in the RGBA8888 pixel format.
    int byteIndex = (bytesPerRow * 0) + 0 * bytesPerPixel;

    CGFloat red   = (rawData[byteIndex]     * 1.0) / 255.0;
    CGFloat green = (rawData[byteIndex + 1] * 1.0) / 255.0;
    CGFloat blue  = (rawData[byteIndex + 2] * 1.0) / 255.0;
    CGFloat alpha = (rawData[byteIndex + 3] * 1.0) / 255.0;

    UIColor *acolor = [UIColor colorWithRed:red green:green blue:blue alpha:alpha];

    free(rawData);

    return acolor;
}

Now if I use this UIColor as the background instead of colorWithPatternImage , I can share to my heart's content without encountering this weird exception.

The above method was adapted from a solution that I found here: https://stackoverflow.com/a/1262893/1103584

It's a bug of iOS 6 i report it and it was marked as dublicate. So, someone report that bug earlier.

For using pattern, you can use resizableImageWithCapInsets. In Monotouch it seems like this:

var sba = UISearchBar.Appearance;

var img = UIImage.FromBundle("myResource.png");

if (UIDevice.CurrentDevice.CheckSystemVersion(6, 0)) {
    img = img.CreateResizableImage(UIEdgeInsets.Zero, UIImageResizingMode.Tile);
    sba.BackgroundColor = UIColor.LightGray;
    sba.BackgroundImage = img;
} else {
    sba.BackgroundImage = new UIImage();
    sba.BackgroundColor = UIColor.FromPatternImage(img);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM