在iPhone上减少Core-Graphics内存消耗

4
我正在编写一个程序,定期重绘一个图形。不幸的是,由于某种原因,核心图形似乎不释放上一个图形,因此我很快就遇到了内存问题。如何在每次绘制结束时强制释放内存?
请注意,这不是内存泄漏,因为当我关闭该视图时,内存确实被释放。我已经尝试将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个回答

2

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

来自Apple文档

The selector must have the following signature:

- (void)timerFireMethod:(NSTimer*)theTimer

你应该使用自己的方法来实现计时器,并从那里调用setNeedsDisplay。正如Robert所说,你应该降低频率,但我认为这些问题都无法解决你的问题。


我所说的这些问题无法解决您的问题,是指:您提供的代码是正确的,没有内存问题。请在其他地方搜索或提供更多的代码。 - Nikolai Ruhe
亲爱的@NikolaiRuhe,请提供苹果文档的链接。这将非常有帮助。不过,感谢您提供的信息。 :) - Abhishek Bedi

1
你尝试过在drawRect方法中使用self.clearsContextBeforeDrawing = YES;吗?

0

+ (Model *) sharedModel { if (sharedModel == nil) sharedModel = [[self alloc] init]; return sharedModel; } 在这段代码中,autorelease丢失了。我认为这也会导致一个内存泄漏。 请尝试使用 sharedModel = [[[self alloc] init] autorelease];


这可能会导致泄漏,但由于它仅在程序开始时初始化一次,所以这不是问题。 - John Smith

0
根据NSTimer文档,最大时间分辨率为50-100毫秒...看起来你正在尝试1毫秒...根据规范,请求比这更精细的计时器不应该导致内存问题,只是不应该像需要的那样频繁触发。我怀疑这是你问题的一部分。

NSTimer类参考

由于典型运行循环管理的各种输入源,计时器的有效分辨率受到限制,约为50-100毫秒。


在完整的程序中,计时器每秒运行一次。那是我创建示例时的一个打字错误。因此,计时器无法解决内存问题。 - John Smith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接