我正在编写一个程序,每隔一段时间就会重新绘制一个图表。不幸的是,似乎由于某种原因核心图形似乎没有释放以前的图形,所以我快速遇到内存问题。如何在每次抽奖结束时强制它释放内存?
这并不是内存泄漏,因为当我离开那个视图时内存会被释放。我试过将NSTimer移到代码中的几个地方都无济于事。
以下是下面的代码,文件从最重要到(可能)不相关。
首先是核心文件+标题,它经常绘制图形(在本例中为正弦波)。
GraphicsView.h
#import <UIKit/UIKit.h>
#import "Model.h"
@interface GraphicsView : UIView
{
Model * model;
}
@end
GraphicsView.m
#import "GraphicsView.h"
@implementation GraphicsView
- (id)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame])
{
model=[Model sharedModel];
[NSTimer scheduledTimerWithTimeInterval:.010 target:self selector:@selector(setNeedsDisplay) userInfo:nil repeats:YES];
}
return self;
}
- (void)drawRect:(CGRect)rect
{
int now=[model n];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClearRect(context, CGRectMake(0, 0, rect.size.width, rect.size.height));
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
CGContextMoveToPoint(context, 0.0, 0.0);
double xc_old=0;
double yc_old=100;
for (int i=0;i<now;i++)
{
double xc=(double)i/(double)now*200;
double yc=100-100*sin((double)i/6);
CGContextMoveToPoint(context, xc_old, yc_old);
CGContextAddLineToPoint(context, xc, yc);
CGContextStrokePath(context);
xc_old=xc;
yc_old=yc;
}
}
- (void)dealloc {
[super dealloc];
}
@end
视图控制器标题:
#import <UIKit/UIKit.h>
#import "GraphicsView.h"
@interface SbarLeakAppDelegate : NSObject <UIApplicationDelegate>
{
UIWindow *window;
Model *model;
GraphicsView * gv;
NSTimer * timer;
}
@end
视图控制器本身。
#import "SbarLeakAppDelegate.h"
@implementation SbarLeakAppDelegate
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
model=[Model sharedModel];
CGRect appRect;
CGRect frame = CGRectInset(appRect, 0.0f, 0.0f);
appRect.origin=CGPointMake(0.0, 40.0);
appRect.size = CGSizeMake(200.0f, 200.0f);
frame = CGRectInset(appRect, 0.0f, 0.0f);
gv=[[GraphicsView alloc] initWithFrame:appRect];
[gv setFrame:frame];
[window addSubview:gv];
[gv release];
[window makeKeyAndVisible];
}
-(void) viewDidAppear:(id)sender
{
//timer=[NSTimer scheduledTimerWithTimeInterval:.250 target:gv selector:@selector(setNeedsDisplay) userInfo:nil repeats:YES];
}
- (void)dealloc
{
[window release];
[super dealloc];
}
@end
此代码仅用于完整性,但(不应)影响该问题。 数据源头文件(只是一个简单的整数)
#import <UIKit/UIKit.h>
@interface Model : NSObject
{
int n;
}
@property int n;
+(Model *) sharedModel;
-(void) inc;
@end
数据源,Model.m:
#import "Model.h"
@implementation Model
static Model * sharedModel = nil;
+ (Model *) sharedModel
{
if (sharedModel == nil)
sharedModel = [[self alloc] init];
return sharedModel;
}
@synthesize n;
-(id) init
{
self=[super init];
[NSTimer scheduledTimerWithTimeInterval:.05 target:self selector:@selector(inc) userInfo:nil repeats:YES];
return self;
}
-(void) inc
{
n++;
}
@end
答案 0 :(得分:2)
您用于计时器的选择器没有正确的签名。
来自Apple docs:
选择器必须具有以下签名:
- (void)timerFireMethod:(NSTimer*)theTimer
您应该使用自己的方法作为计时器并从那里调用setNeedsDisplay
。正如罗伯特所说,你应该稍微调低频率,但我不认为这些问题中的任何一个都能解决你的问题。
答案 1 :(得分:1)
您是否在self.clearsContextBeforeDrawing = YES;
方法中尝试了drawRect
?
答案 2 :(得分:0)
根据NSTimer文档,最大时间分辨率是50-100ms ...看起来你正在尝试1ms ......根据规格要求更高分辨率的定时器不应该导致内存问题,它不应该根据需要经常开火。不过,我怀疑这是你问题的一部分。
由于各种输入源a 典型的运行循环管理, 有效解决时间问题 计时器的间隔限制为开启 大约50-100毫秒。
答案 3 :(得分:0)
+ (Model *) sharedModel
{
if (sharedModel == nil)
sharedModel = [[self alloc] init];
return sharedModel;
}
在这个片段中,缺少自动释放。我认为这也会导致泄漏。
尝试
sharedModel = [[[self alloc] init] autorelease];