目前,我的一款游戏正在使用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
感谢任何建议。