IOS6和UIImage的奇怪问题

时间:2012-09-27 07:51:19

标签: memory-management uikit uiimage ios6

目前,我的一款游戏正在使用UIKit,其图像来自spritesheets。在IOS6之前,在标题屏幕上使用的总内存大小为80mb,但在IOS6,它的峰值达到300MB。即使我删除了UIKit,所使用的内存仍然是来自Cocos2d的80mb-90mb。任何人都知道为什么会这样?

下面是我缓存纹理并使用它们的代码:

//this function will be called at the beginning of the app to cache the image, so far it does not cause any memory spike.
+(void) cacheCommonlyUsedTexture
{
    cachedSpriteFrames = [[NSMutableDictionary alloc] initWithCapacity:0];
    cachedSprite = [[NSMutableDictionary alloc] initWithCapacity:0];
    NSString* levelPath = [ [NSBundle mainBundle] pathForResource:texName ofType:@"plist"];
    NSString* imagePath = [ [NSBundle mainBundle] pathForResource:texName ofType:@"png"];
    cachedFrameDict = [[NSDictionary dictionaryWithContentsOfFile:levelPath] retain];
    NSData* tempData = [[NSData alloc] initWithContentsOfFile:imagePath];
    UIImage* mainImg = [[UIImage alloc] initWithData:tempData];
    NSDictionary* dict = [cachedFrameDict objectForKey:@"frames"];
    for (id key in [dict allKeys])
    {
        NSDictionary* spriteDict = [dict objectForKey:key];
        if (spriteDict)
        {
            CGRect frameOfSprite = CGRectFromString( [spriteDict objectForKey:@"frame"]);

            CGImageRef imageRef = CGImageCreateWithImageInRect([mainImg CGImage], frameOfSprite);
            UIImage* image = [[UIImage alloc]  initWithCGImage:imageRef];
            CGImageRelease(imageRef);
            if (image)
            {
                [cachedSpriteFrames setObject:image forKey:key];
                [image release];
            }
        }
    }
    [mainImg release];

}

//this selector actually gets the spriteframe
+(UIImage*) imageFromPlist:(NSString*) plist withFrameName:(NSString*) frameName
{

    NSDictionary* fileDict;
    UIImage* mainImg;
    NSData* mainData;
    if ([plist isEqualToString:texName] && [cachedSpriteFrames objectForKey:frameName])
    {
        id returnImage = [[cachedSpriteFrames objectForKey:frameName] retain];
        return returnImage;
    }
    else
    {
        NSString* imagePath = [ [NSBundle mainBundle] pathForResource:plist ofType:@"png"];

        NSString* levelPath = [ [NSBundle mainBundle] pathForResource:plist ofType:@"plist"];
        fileDict = [NSDictionary dictionaryWithContentsOfFile:levelPath];
        mainData = [NSData dataWithContentsOfFile:imagePath];

    }
    mainImg = [[UIImage alloc] initWithData:mainData];

    if (fileDict)
    {
        NSDictionary* frameDict = [fileDict objectForKey:@"frames"];
        if (frameDict)
        {
            NSDictionary* spriteDict = [frameDict objectForKey:frameName];
            if (spriteDict)
            {
                CGRect frameOfSprite = CGRectFromString( [spriteDict objectForKey:@"frame"]);

                CGImageRef imageRef = CGImageCreateWithImageInRect([mainImg CGImage], frameOfSprite);
                UIImage* image = [[UIImage alloc]  initWithCGImage:imageRef];
                CGImageRelease(imageRef);
                [mainImg release];
                return image;
            }
        }
    }
    [mainImg release];
    return nil;
}

我的加载代码:

@implementation CustomImageView (PlistLoading)
//my UIKit elements are loaded from a plist.
-(id) initWithDictionary:(NSDictionary *)dict withParentView:(id)pView
{
    if ((self = [super initWithDictionary:dict withParentView:pView]))
    {
        self.userInteractionEnabled = NO; //the image views should not receive inputs
        UIImage* image = nil;
        self.backgroundColor = [UIColor clearColor];
        if ([dict objectForKey:@"spritesheet"])
        {
            image = [UIImage imageFromPlist:[dict objectForKey:@"spritesheet"] withFrameName:[dict objectForKey:@"spriteframe"]];

        }
        else
        {
            if ([dict objectForKey:@"imageFile"])
            {

                image = [UIImage spriteFromCache:[dict objectForKey:@"imageFile"]];

            }
        }
        if (image)
        {
            if ([dict objectForKey:@"flip"])
            {
                if ([[dict objectForKey:@"flip"] boolValue])
                {
                    CGImageRef imageRef = image.CGImage;
                    UIImage* image2 = image;
                    image = [[UIImage imageWithCGImage:imageRef scale:1.0 orientation:UIImageOrientationUpMirrored] retain];
                    [image2 release];
                    self.flipX = YES;
                }
            }
            self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, image.size.width, image.size.height);
            self.image = image;
            [image release];
            //[image release];
        }

    }
    return self;
}

@end

最后,我在CustomImageView.h和.m中使用了什么。我使用CustomImageView而不是UIImageView的原因是它似乎比UIImageView使用更少的内存:

#import <UIKit/UIKit.h>

@interface CustomImageView : UIView
{
    CALayer* imageLayer;
}
@property (nonatomic, retain) UIImage* image;
@property (nonatomic) BOOL drawBorder;
@property (nonatomic) BOOL flipX;
-(void) drawImage:(CGRect) rect;
@end

#import "CustomImageView.h"
#import "UIView+PlistLoading.h"
#import <QuartzCore/QuartzCore.h>
@implementation CustomImageView
@synthesize image, drawBorder, flipX;
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        drawBorder = NO;
        imageLayer = nil;
        self.backgroundColor = [UIColor clearColor];
    }
    return self;
}
-(void) removeFromSuperview
{
    self.image = nil;
    imageLayer.contents = nil;
    [imageLayer removeFromSuperlayer];
    //[imageLayer release];
    [super removeFromSuperview];
}
-(void) dealloc
{
    [super dealloc];
}
-(void) setImage:(UIImage *)myImage
{

    imageLayer = [CALayer layer];
    imageLayer.frame = self.bounds;
    imageLayer.contents = (id) myImage.CGImage;
    imageLayer.masksToBounds = YES;
    if (flipX)
    {
        [imageLayer setAffineTransform:CGAffineTransformMakeScale(-1, 1)];
    }
    [self.layer addSublayer:imageLayer];
    //[imageLayer release];
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.

*/
-(void) drawImage:(CGRect) rect
{
    if (self.image)
    {


        //[self.image drawInRect:rect];

        if (drawBorder)
        {
            CGContextRef context = UIGraphicsGetCurrentContext();
            CGContextSetStrokeColorWithColor(context, self.layer.borderColor);
            CGContextSetLineWidth(context, self.layer.borderWidth);
            UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:self.layer.cornerRadius];
            [path addClip];

        }
        else
        {

        }
    }
}
- (void)drawRect:(CGRect)rect
{
    // Drawing code
    [self drawImage:rect];
}
@end

感谢任何建议。

0 个答案:

没有答案