1

xml ドキュメントの 1 つを解析しているときにメモリ リークが発生して困っています。

NSXMLParser を使用して各ノード (以下の xml サンプルのアルバム) を反復し、次に各写真ノードを反復し、結果を NSArray に追加します。

各ループに 2 つの値を格納する 2 つの保持プロパティがあります。これらの値は、各写真ノードを含む別の NSArray と共に NSMutableDictionary オブジェクトに追加されます。結果の辞書は NSArray に追加され、アプリケーションの他の場所で使用されます。

アプリケーションの特定の時点で xml ドキュメントをリロードするボタンがあります。次に呼び出されるのは、リークが発生したときです。Instruments は、NSCFArray と NSCFString がリークしていることを示しており、didEndElement に表示されています。

一体どこで私は間違っているのでしょう。どんなアドバイスも役に立ちます。

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if([elementName isEqualToString:@"photo"]){
    self.strPhotoPath = [attributeDict objectForKey:@"iphone"];
}else if ([elementName isEqualToString:@"album"]) {

    dicItem = [[[NSMutableDictionary alloc] init] autorelease];

    self.strCurrentTitle = [attributeDict objectForKey:@"band_name"];
    self.strCurrentLocation = [attributeDict objectForKey:@"location"];

}
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{   
if([elementName isEqualToString:@"photo"]){
    [self.arrPhotos addObject:self.strPhotoPath];
}else if ([elementName isEqualToString:@"album"]) {
    [dicItem setObject:self.strCurrentTitle forKey:@"album"];
    [dicItem setObject:self.strCurrentLocation forKey:@"location"];
    [dicItem setObject:[self.arrPhotos copy] forKey:@"photos"];

    [self.arrAlbums addObject:dicItem];

    [self.arrPhotos removeAllObjects];
}
}

xml の一部を次に示します。

<albums type='array'>
<album location='Album 1' date='2009-12-04 22:47:48 UTC' album_name='' band_name='Band 1'>
<photo display_on_website='true' standard='/system/photos/3396/original/Photo1-DSC8894.jpg' thumb='/system/photos/3396/thumb/Photo1-DSC8894.jpg' date='2009-12-04 22:47:48' exif_data='NIKON D300, F:2.8, Shutter:1/80, Focal:15mm, ISO:1600' iphone='/system/photos/3396/iPhone/Photo2-DSC8894.jpg' available_for_print='false'/>
<photo display_on_website='true' standard='/system/photos/3403/original/Photo2-DSC9146.jpg' thumb='/system/photos/3403/thumb/Photo3-DSC9146.jpg' date='2009-12-04 23:19:27' exif_data='NIKON D300, F:4.5, Shutter:1/160, Focal:70mm, ISO:1600' iphone='/system/photos/3403/iPhone/Photo3-DSC9146.jpg' available_for_print='false'/>
</album>
<album location='Album 2' date='2009-12-04 22:47:48 UTC' album_name='' band_name='Band 2'>
<photo display_on_website='true' standard='/system/photos/3396/original/Photo3-DSC8894.jpg' thumb='/system/photos/3396/thumb/Photo3-DSC8894.jpg' date='2009-12-04 22:47:48' exif_data='NIKON D300, F:2.8, Shutter:1/80, Focal:15mm, ISO:1600' iphone='/system/photos/3396/iPhone/Photo3-DSC8894.jpg' available_for_print='false'/>
<photo display_on_website='true' standard='/system/photos/3403/original/Photo4-DSC9146.jpg' thumb='/system/photos/3403/thumb/Photo4-DSC9146.jpg' date='2009-12-04 23:19:27' exif_data='NIKON D300, F:4.5, Shutter:1/160, Focal:70mm, ISO:1600' iphone='/system/photos/3403/iPhone/Photo4-DSC9146.jpg' available_for_print='false'/>
<photo display_on_website='true' standard='/system/photos/3403/original/Photo5-DSC9146.jpg' thumb='/system/photos/3403/thumb/Photo5-DSC9146.jpg' date='2009-12-04 23:19:27' exif_data='NIKON D300, F:4.5, Shutter:1/160, Focal:70mm, ISO:1600' iphone='/system/photos/3403/iPhone/Photo5-DSC9146.jpg' available_for_print='false'/>
</album>
</albums>
4

1 に答える 1

1
[dicItem setObject:[self.arrPhotos copy] forKey:@"photos"];

この行が犯人だと思います。albumコピーが自動解放または解放されることはなく、パーサーが要素に遭遇するたびに置き換えられるだけです。使用する:

[dicItem setObject:[[self.arrPhotos copy] autorelease] forKey:@"photos"];

配列のコピーを作成しているため、配列内のすべてのオブジェクトの保持カウントも増加します。そのため、(辞書で上書きすることによって) 配列に到達できなくなった場合、配列に含まれていたすべての文字列は解放されません。正しく、配列もそうではありません。

于 2009-12-07T21:51:47.030 に答える