0

私が書いた現在のコードでメモリに小さな問題があります。私はココアとオブジェクト指向言語でのプログラミングは初めてなので、現在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

各行で、テーブル ビューを再割り当てしているようです。

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

フレーム サイズが非常に奇数であることを除けば、テーブル ビューを再作成するべきではありません。データをリロードする場合は、 を呼び出すだけで-reloadData、テーブル ビューの削除と追加を繰り返さないでください。ARC を使用しているかどうかはわかりませんが、おそらく問題は、テーブル ビューが占有していた古いメモリを解放していないことですが、代わりに新しいインスタンスを古い ivar に割り当てていることです。古いインスタンスはまだどこかにぶら下がっていますが、ポインターを再割り当てしたため、アクセスできません。

-drawRect:また、非常に多くの理由で恐ろしい、この奇妙なリロード作業をすべて行っています。

于 2012-11-29T21:18:10.767 に答える
1

image_view2 で alloc/init を呼び出す必要がありますか? 毎回サイズをハードコーディングしているので、新しい画像を設定するだけでいいのですか?

于 2012-11-29T21:13:52.460 に答える