0

我编写的当前代码在内存方面存在一个小问题,我是 cocoa 和使用面向对象语言编程的新手,所以目前 Xcode 为我完成了所有内存管理工作,但是现在这对我没有帮助。

目前的问题是我正在创建一个 NSTableView 并且它在每个单元格中都有图片以 0.5 秒的间隔更新,这很好,但是每次加载图像时都会创建一个新的 NSImageView 对象(这是我认为内存问题是,如果我错了,请纠正我),我如何缺乏解决这个问题的方法。这导致内存使用量每 0.5 秒增加约 5MB,因此在 10 分钟左右后,应用程序将占用我计算机内存的很大一部分。不知道创建的 NSImageView 对象没用后怎么去掉,又不会导致图片在显示过程中出现延迟...

这是当前代码:

-(void)play_view:(NSInteger)view{
     valid_times_counter = valid_times_counter + 1;
     if(valid_times_counter == ([valid_times count]-2)){
         valid_times_counter = 1;
     }
     [self performSelector:@selector(reload_table_data) withObject:self afterDelay:0.5];
}

-(void)reload_table_data{
    [view_table removeFromSuperview];
    [self addSubview:view_table];
    [view_table reloadData];
    [self play_view:valid_times_counter];
}

- (void)drawRect:(NSRect)dirtyRect
{
NSLog(@"drawing"); //Table being drawn, probably not relevant but just in case ;)

[[NSColor colorWithCalibratedRed:0.01f green:0.40f blue:0.69f alpha:1.00f]setFill];
NSRect bg = NSMakeRect(0, 0, self.frame.size.width, self.frame.size.height);
NSRectFill(bg);

if(level == 1){
    NSLog(@"draw_table Level 1");
    [view_table removeFromSuperview];
    [self setFrameSize:NSMakeSize(2048, 1024)];
    view_table = [[NSTableView alloc]initWithFrame:NSMakeRect(0, self.frame.size.height-1024, 2048, 1024)];
    for(int c = 0; c<4;c++){
        NSTableColumn *column = [[NSTableColumn alloc] initWithIdentifier:[NSString stringWithFormat:@"%i",c]];
        [[column headerCell] setStringValue:[NSString stringWithFormat:@"%i",c]];
        [column setWidth:512.0];
        [view_table addTableColumn:column];
    }
    [view_table setRowHeight:512];
    [view_table setDelegate:(id)self];
    [view_table setDataSource:(id)self];
    [view_table setIntercellSpacing:NSMakeSize(0, 0)];
    [view_table setIdentifier:@"view_table"];
    [view_table reloadData];

    [self addSubview:view_table];

}
else if(level == 2){
    NSLog(@"draw_table Level 2");
    [view_table removeFromSuperview];
    [self setFrameSize:NSMakeSize(4096, 2048)];
    view_table = [[NSTableView alloc]initWithFrame:NSMakeRect(0, self.frame.size.height-2048, 4096, 2048)];
    for(int c = 0; c<8;c++){
        NSTableColumn *column = [[NSTableColumn alloc] initWithIdentifier:[NSString stringWithFormat:@"%i",c]];
        [[column headerCell] setStringValue:[NSString stringWithFormat:@"%i",c]];
        [column setWidth:512.0];
        [view_table addTableColumn:column];
    }
    [view_table setRowHeight:512];
    [view_table setDelegate:(id)self];
    [view_table setDataSource:(id)self];
    [view_table setIntercellSpacing:NSMakeSize(0, 0)];
    [view_table setIdentifier:@"view_table"];
    [view_table reloadData];

    [self addSubview:view_table];
}
else if(level == 3){
    NSLog(@"draw_table Level 3");
    [view_table removeFromSuperview];
    [self setFrameSize:NSMakeSize(8192, 4096)];
    view_table = [[NSTableView alloc]initWithFrame:NSMakeRect(0, self.frame.size.height-4096, 8192, 4096)];
    for(int c = 0; c<16;c++){
        NSTableColumn *column = [[NSTableColumn alloc] initWithIdentifier:[NSString stringWithFormat:@"%i",c]];
        [[column headerCell] setStringValue:[NSString stringWithFormat:@"%i",c]];
        [column setWidth:512.0];
        [view_table addTableColumn:column];
    }
    [view_table setRowHeight:512];
    [view_table setBackgroundColor:[NSColor clearColor]];
    [view_table setDelegate:(id)self];
    [view_table setDataSource:(id)self];
    [view_table setIntercellSpacing:NSMakeSize(0, 0)];
    [view_table setIdentifier:@"view_table"];
    [view_table reloadData];

    [self addSubview:view_table];
}
else if(level == 4){
    NSLog(@"draw_table Level 4");
    [view_table removeFromSuperview];
    [self setFrameSize:NSMakeSize(16384, 8192)];
    view_table = [[NSTableView alloc]initWithFrame:NSMakeRect(0, self.frame.size.height-8192, 16384, 8192)];
    for(int c = 0; c<32;c++){
        NSTableColumn *column = [[NSTableColumn alloc] initWithIdentifier:[NSString stringWithFormat:@"%i",c]];
        [[column headerCell] setStringValue:[NSString stringWithFormat:@"%i",c]];
        [column setWidth:512.0];
        [view_table addTableColumn:column];
    }
    [view_table setRowHeight:512];
    [view_table setDelegate:(id)self];
    [view_table setDataSource:(id)self];
    [view_table setIntercellSpacing:NSMakeSize(0, 0)];
    [view_table setIdentifier:@"view_table"];
    [view_table reloadData];

    [self addSubview:view_table];
}
else if(level == 5){
    NSLog(@"draw_table Level 5");
    [view_table removeFromSuperview];
    [self setFrameSize:NSMakeSize(32768, 16384)];
    view_table = [[NSTableView alloc]initWithFrame:NSMakeRect(0, self.frame.size.height-16384, 32768, 16384)];
    for(int c = 0; c<64;c++){
        NSTableColumn *column = [[NSTableColumn alloc] initWithIdentifier:[NSString stringWithFormat:@"%i",c]];
        [[column headerCell] setStringValue:[NSString stringWithFormat:@"%i",c]];
        [column setWidth:512.0];
        [view_table addTableColumn:column];
    }
    [view_table setRowHeight:512];
    [view_table setBackgroundColor:[NSColor clearColor]];
    [view_table setDelegate:(id)self];
    [view_table setDataSource:(id)self];
    [view_table setIntercellSpacing:NSMakeSize(0, 0)];
    [view_table setIdentifier:@"view_table"];
    [view_table reloadData];

    [self addSubview:view_table];
}


//Problem section
-(NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row{

if([tableView.identifier isEqualToString: @"view_table"]){
    NSLog(@"---------VIEW---------");
    NSView *view = [tableView makeViewWithIdentifier:@"MyView2" owner:self];
    [tableView setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleNone];

    if (view == nil) {
        view = [[NSView alloc]initWithFrame:NSMakeRect(0, 0, 512, 512)];
        NSString *table_id;
        if([tableColumn.identifier integerValue]<10){
            table_id = [NSString stringWithFormat:@"000%@",tableColumn.identifier];
        }
        else if([tableColumn.identifier integerValue]<100){
            table_id = [NSString stringWithFormat:@"00%@",tableColumn.identifier];
        }
        else if([tableColumn.identifier integerValue]<1000){
            table_id = [NSString stringWithFormat:@"0%@",tableColumn.identifier];
        }
        NSString *row_id;
        if(row < 10){
            row_id = [NSString stringWithFormat:@"000%li",row];
        }
        else if(row < 100){
            row_id = [NSString stringWithFormat:@"00%li",row];
        }
        else if(row < 1000){
            row_id = [NSString stringWithFormat:@"0%li",row];
        }

        if([valid_times count]>1){
            image_view2 = [[NSImageView alloc] initWithFrame:NSMakeRect(0, 0, 512, 512)]; //This gets repeated every 0.5s, and this is what is causing the problem I think...
            NSString *url_str = [self get_url:(valid_times_counter):table_id:row_id];
            NSLog(@"Loading Image from: %@", url_str);
            NSImage *map_tile2 = [[NSImage alloc] initWithContentsOfFile:url_str];
            [image_view2 setImage:map_tile2];
            [view addSubview:image_view2];
        }
        else{
            //No Views found
            NSLog(@"ERROR, NO IMAGES FOUND 348.map_view.h-tableView.viewForTableColumn:row For data %@", [valid_times objectAtIndex:0]);
        }
    }
    return view;

我已经在代码中评论了我认为问题所在的部分,有没有人知道解决方案,我想只是更改单元格的内容而不是每次都重新加载表格数据,但我真的不知道如何去做。

如果您需要更多详细信息,请询问,我会很乐意提供任何想法...

4

2 回答 2

1

你必须在 image_view2 上调用 alloc/init 吗?由于您每次都对尺寸进行硬编码,因此您似乎可以设置新图像?

于 2012-11-29T21:13:52.460 回答
1

在每一行上,您似乎都在重新分配您的表格视图。

view_table = [[NSTableView alloc]initWithFrame:NSMakeRect(0, self.frame.size.height-4096, 8192, 4096)];

撇开帧大小的奇数数字不谈,您不应该重新创建表格视图。如果要重新加载数据,只需调用-reloadData,但不要一直删除和添加表格视图。我不知道您是否使用 ARC,但很可能您的问题是您没有释放表视图占用的旧内存,而是为旧 ivar 分配了一个新实例。旧实例仍在某处,但您无法访问它,因为您重新分配了指针。

你也在做所有这些奇怪的重新加载的东西,-drawRect:其中有很多原因是可怕的。

于 2012-11-29T21:18:10.767 回答