我在使用ARC的iPhone应用程序时遇到了一个相当严重的问题。
我有一个viewcontroller(让我们称之为A)。这个viewcontroller打开一个导航控制器作为模态,它运行3个不同的视图控制器(让我们称之为1,2和3)。在查看3号后,导航控制器关闭,我们再次回到A.
所以流程是:A打开导航控制器并经过1-> 2-> 3然后再次关闭。
每次经历这种流动,我都会失去记忆。我搜索了所有文件,寻找任何保留og强大的属性,未失效的计时器或类似的东西,以解决这个问题。
我有一个想法,这可能是问题所在。在viewcontroller 1中,我使用coreanimation和sprite呈现动画。我正在使用其他人的实现。似乎如果我禁用动画,使用的内存似乎非常恒定(从而没有内存丢失)。我已经修改了一些实现ARC的实现。这是我用于精灵动画的实现:
MCSpriteLayer.h
//
// MCSpriteLayer.h
//
// Created by Miguel Angel Friginal on 8/20/10.
// Copyright 2010 Mystery Coconut Games. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <QuartzCore/QuartzCore.h>
@interface MCSpriteLayer : CALayer {
unsigned int sampleIndex;
}
// SampleIndex needs to be > 0
@property (nonatomic) unsigned int sampleIndex;
// For use with sample rects set by the delegate
+ (id)layerWithImage:(CGImageRef)img;
- (id)initWithImage:(CGImageRef)img;
// If all samples are the same size
+ (id)layerWithImage:(CGImageRef)img sampleSize:(CGSize)size :(int)useRetina;
- (id)initWithImage:(CGImageRef)img sampleSize:(CGSize)size;
// Use this method instead of sprite.sampleIndex to obtain the index currently displayed on screen
- (unsigned int)currentSampleIndex;
@end
MCSpriteLayer.m
//
// MCSpriteLayer.m
//
// Created by Miguel Angel Friginal on 8/20/10.
// Copyright 2010 Mystery Coconut Games. All rights reserved.
//
#import "MCSpriteLayer.h"
@implementation MCSpriteLayer
@synthesize sampleIndex;
#pragma mark -
#pragma mark Initialization, variable sample size
- (id)initWithImage:(CGImageRef)img;
{
self = [super init];
if (self != nil)
{
self.contents = (__bridge id)img;
sampleIndex = 1;
}
return self;
}
+ (id)layerWithImage:(CGImageRef)img;
{
MCSpriteLayer *layer = [(MCSpriteLayer*)[self alloc] initWithImage:img];
return layer;
}
#pragma mark -
#pragma mark Initialization, fixed sample size
- (id)initWithImage:(CGImageRef)img sampleSize:(CGSize)size;
{
self = [self initWithImage:img];
if (self != nil)
{
CGSize sampleSizeNormalized = CGSizeMake(size.width/CGImageGetWidth(img), size.height/CGImageGetHeight(img));
self.bounds = CGRectMake( 0, 0, size.width, size.height );
self.contentsRect = CGRectMake( 0, 0, sampleSizeNormalized.width, sampleSizeNormalized.height );
}
return self;
}
+ (id)layerWithImage:(CGImageRef)img sampleSize:(CGSize)size :(int)useRetina;
{
CGSize newSampleSize;
if(useRetina == 1) {
// Supporting retina displays
if ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)] &&
([UIScreen mainScreen].scale == 2.0)) {
newSampleSize = CGSizeMake(size.width*2, size.height*2);
} else {
newSampleSize = size;
}
} else
newSampleSize = size;
MCSpriteLayer *layer = [[self alloc] initWithImage:img sampleSize:newSampleSize];
return layer;
}
#pragma mark -
#pragma mark Frame by frame animation
+ (BOOL)needsDisplayForKey:(NSString *)key;
{
return [key isEqualToString:@"sampleIndex"];
}
// contentsRect or bounds changes are not animated
+ (id < CAAction >)defaultActionForKey:(NSString *)aKey;
{
if ([aKey isEqualToString:@"contentsRect"] || [aKey isEqualToString:@"bounds"])
return (id < CAAction >)[NSNull null];
return [super defaultActionForKey:aKey];
}
- (unsigned int)currentSampleIndex;
{
return ((MCSpriteLayer*)[self presentationLayer]).sampleIndex;
}
// Implement displayLayer: on the delegate to override how sample rectangles are calculated; remember to use currentSampleIndex, ignore sampleIndex == 0, and set the layer's bounds
- (void)display;
{
if ([self.delegate respondsToSelector:@selector(displayLayer:)])
{
[self.delegate displayLayer:self];
return;
}
unsigned int currentSampleIndex = [self currentSampleIndex];
if (!currentSampleIndex)
return;
CGSize sampleSize = self.contentsRect.size;
self.contentsRect = CGRectMake(
((currentSampleIndex - 1) % (int)(1/sampleSize.width)) * sampleSize.width,
((currentSampleIndex - 1) / (int)(1/sampleSize.width)) * sampleSize.height,
sampleSize.width, sampleSize.height
);
}
@end
这种实现是否在某种程度上没有正确地重新发布或保留任何内容?提前谢谢。
更新 - 我正在使用仪器测量内存。我正在使用内存监视器,我会关注物理内存自由 - 图像创建如下:
NSString *path = [[NSBundle mainBundle] pathForResource:@"round_start.png" ofType:nil];
CGSize fixedSize = CGSizeMake(320, 480);
mascot = [MCSpriteLayer layerWithImage:[UIImage imageWithContentsOfFile:path].CGImage sampleSize:fixedSize :0];
mascot.frame = CGRectMake(ANIMATION_X, ANIMATION_Y, ANIMATION_WIDTH, ANIMATION_HEIGHT);
[self.view.layer addSublayer:mascot2];
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"sampleIndex"];
anim.delegate = self;
anim.fromValue = [NSNumber numberWithInt:1];
anim.toValue = [NSNumber numberWithInt:52];
anim.duration = ANIMATION_DURATION;
anim.repeatCount = 1;
[mascot addAnimation:anim forKey:nil];
- 我一直在用
关闭模态[self dismissModalViewControllerAnimated:YES];
和
[self.navigationController dismissModalViewControllerAnimated:YES];
答案 0 :(得分:1)
解雇导航控制器不会释放它,假设你有一个强引用它(需要得到nil'd)。在它使用的视图控制器中,在dealloc方法中添加一条日志消息,因此您知道它们已被解除分配(您可以对任何子类化项执行此操作)。如果需要,您可以创建一个简单的UINavigation子类,其唯一目的是在dealloc中添加消息。您会发现这些项目中的一个或多个未被解除分配,然后您需要确定它们是由属性/ ivar保留还是因为它们仍然具有超级视图。