4

我正在编写一个程序,它经常重绘一个图表。不幸的是,由于某种原因,核心图形似乎没有释放以前的图形,所以我很快就遇到了内存问题。如何强制它在每次绘制结束时释放内存?

并不是说这不是内存泄漏,因为当我关闭该视图时内存确实会被释放。我尝试将 NSTimer 移动到代码中的几个位置,但无济于事。

这是下面的代码,文件从最重要到(可能)不相关。

首先是每隔一段时间绘制图形(在这种情况下为正弦波)的核心文件+标题。

图形视图.h

#import <UIKit/UIKit.h>
#import "Model.h"

@interface GraphicsView : UIView 
{
    Model * model;
} 
@end

图形视图.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
4

4 回答 4

2

您用于计时器的选择器没有正确的签名。

来自苹果文档

选择器必须具有以下签名:

- (void)timerFireMethod:(NSTimer*)theTimer

您应该使用自己的计时器方法并setNeedsDisplay从那里调用。正如罗伯特所说,你应该把频率调低一点,但我认为这两个问题都不能解决你的问题。

于 2009-07-27T15:28:22.673 回答
1

您是否尝试过:self.clearsContextBeforeDrawing = YES;drawRect方法中?

于 2012-12-03T09:14:51.053 回答
0

+ (Model *) sharedModel { if (sharedModel == nil) sharedModel = [[self alloc] init]; return sharedModel; } 在此代码段中,缺少自动释放。我认为这也会导致泄漏。尝试 sharedModel = [[[self alloc] init] autorelease];

于 2010-06-09T18:52:26.143 回答
0

根据 NSTimer 文档,最大时间分辨率为 50-100 毫秒...看起来您正在尝试 1 毫秒...根据规范,要求更精细分辨率的计时器不会导致内存问题,它只是不应该根据需要经常开火。不过,我怀疑这是您问题的一部分。

NSTimer 类参考

由于典型的运行循环管理的各种输入源,计时器的时间间隔的有效分辨率被限制在 50-100 毫秒的数量级。

于 2009-07-27T15:09:24.037 回答