减少iphone上的核心图形内存消耗

时间:2009-07-27 15:00:13

标签: iphone memory-management uiview core-graphics

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

这并不是内存泄漏,因为当我离开那个视图时内存会被释放。我试过将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

4 个答案:

答案 0 :(得分:2)

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

来自Apple docs

  

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

- (void)timerFireMethod:(NSTimer*)theTimer

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

答案 1 :(得分:1)

您是否在self.clearsContextBeforeDrawing = YES;方法中尝试了drawRect

答案 2 :(得分:0)

根据NSTimer文档,最大时间分辨率是50-100ms ...看起来你正在尝试1ms ......根据规格要求更高分辨率的定时器不应该导致内存问题,它不应该根据需要经常开火。不过,我怀疑这是你问题的一部分。

NSTimer Class Reference

  

由于各种输入源a   典型的运行循环管理,   有效解决时间问题   计时器的间隔限制为开启   大约50-100毫秒。

答案 3 :(得分:0)

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