gpt4 book ai didi

ios - 重新加载对象时 NSMutableArray 内存泄漏

转载 作者:行者123 更新时间:2023-11-29 11:12:03 25 4
gpt4 key购买 nike

我正在使用 Three20/TTThumbsviewcontroller 加载照片。很长一段时间以来,我一直在努力解决设置照片源时的内存泄漏问题。我是 Object C 和 iOS 内存管理的初学者。请查看以下代码,并提出任何明显的错误或声明和释放变量的任何错误。

-- PhotoViewController.h

 @interface PhotoViewController : TTThumbsViewController <UIPopoverControllerDelegate,CategoryPickerDelegate,FilterPickerDelegate,UISearchBarDelegate>{
......
NSMutableArray *_photoList;

......
@property(nonatomic,retain) NSMutableArray *photoList;

-- PhotoViewController.m

@implementation PhotoViewController
....

@synthesize photoList;
.....

- (void)LoadPhotoSource:(NSString *)query:(NSString *)title:(NSString* )stoneName{


NSLog(@"log- in loadPhotosource method");


if (photoList == nil)
photoList = [[NSMutableArray alloc] init ];

[photoList removeAllObjects];



@try {
sqlite3 *db;
NSFileManager *fileMgr = [NSFileManager defaultManager];
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];

NSString *dbPath = [documentsPath stringByAppendingPathComponent: @"DB.s3db"];
BOOL success = [fileMgr fileExistsAtPath:dbPath];
if(!success)
{
NSLog(@"Cannot locate database file '%@'.", dbPath);
}

if(!(sqlite3_open([dbPath UTF8String], &db) == SQLITE_OK))
{
NSLog(@"An error has occured.");
}


NSString *_sql = query;
const char *sql = [_sql UTF8String];
sqlite3_stmt *sqlStatement;
if(sqlite3_prepare(db, sql, -1, &sqlStatement, NULL) != SQLITE_OK)
{
NSLog(@"Problem with prepare statement");
}

if ([stoneName length] != 0)
{
NSString *wildcardSearch = [NSString stringWithFormat:@"%@%%",[stoneName stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];

sqlite3_bind_text(sqlStatement, 1, [wildcardSearch UTF8String], -1, SQLITE_STATIC);
}


while (sqlite3_step(sqlStatement)==SQLITE_ROW) {

NSString* urlSmallImage = @"Mahallati_NoImage.png";
NSString* urlThumbImage = @"Mahallati_NoImage.png";


NSString *designNo = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement,2)];
designNo = [designNo stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

NSString *desc = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement,7)];
desc = [desc stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

NSString *caption = designNo;//[designNo stringByAppendingString:desc];
caption = [caption stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];



NSString *smallFilePath = [documentsPath stringByAppendingPathComponent: [NSString stringWithFormat:@"Small%@.JPG",designNo] ];
smallFilePath = [smallFilePath stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if ([fileMgr fileExistsAtPath:smallFilePath]){
urlSmallImage = [NSString stringWithFormat:@"Small%@.JPG",designNo];
}

NSString *thumbFilePath = [documentsPath stringByAppendingPathComponent: [NSString stringWithFormat:@"Thumb%@.JPG",designNo] ];
thumbFilePath = [thumbFilePath stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

if ([fileMgr fileExistsAtPath:thumbFilePath]){
urlThumbImage = [NSString stringWithFormat:@"Thumb%@.JPG",designNo];
}




NSNumber *photoProductId = [NSNumber numberWithInt:(int)sqlite3_column_int(sqlStatement, 0)];
NSNumber *photoPrice = [NSNumber numberWithInt:(int)sqlite3_column_int(sqlStatement, 6)];

char *productNo1 = sqlite3_column_text(sqlStatement, 3);
NSString* productNo;
if (productNo1 == NULL)
productNo = nil;
else
productNo = [NSString stringWithUTF8String:productNo1];

Photo *jphoto = [[[Photo alloc] initWithCaption:caption
urlLarge:[NSString stringWithFormat:@"documents://%@",urlSmallImage]
urlSmall:[NSString stringWithFormat:@"documents://%@",urlSmallImage]
urlThumb:[NSString stringWithFormat:@"documents://%@",urlThumbImage]
size:CGSizeMake(123, 123)
productId:photoProductId
price:photoPrice
description:desc
designNo:designNo
productNo:productNo
] autorelease];



[photoList addObject:jphoto];
[jphoto release];



}


}
@catch (NSException *exception) {
NSLog(@"An exception occured: %@", [exception reason]);
}



self.photoSource = [[[MockPhotoSource alloc]
initWithType:MockPhotoSourceNormal
title:[NSString stringWithFormat: @"%@",title]
photos: photoList
photos2:nil] autorelease];

}

使用不同的查询再次调用上述 LoadPhotosource 方法时会发生内存泄漏...我觉得声明 NSMutableArray (photoList) 有问题,但无法弄清楚如何修复内存泄漏。非常感谢任何建议。

最佳答案

我没有在您的代码中看到任何泄漏的对象,但实际上是双重释放的对象,最终会使您的应用程序崩溃:

在你的最后几行中,你有这个:

Photo *jphoto = [[[Photo alloc] initWithCaption:caption
urlLarge:[NSString stringWithFormat:@"documents://%@",urlSmallImage]
urlSmall:[NSString stringWithFormat:@"documents://%@",urlSmallImage]
urlThumb:[NSString stringWithFormat:@"documents://%@",urlThumbImage]
size:CGSizeMake(123, 123)
productId:photoProductId
price:photoPrice
description:desc
designNo:designNo
productNo:productNo
] autorelease];



[photoList addObject:jphoto];
[jphoto release];

如果你仔细观察,你有一个双重释放(alloc 中的自动释放和 addObject 之后的释放)。您应该删除其中一个。

除此之外,我还向您推荐一些东西:

  1. 切换到 ARC:如果您是新手,您肯定会利用它,因为您将不必再担心几乎所有的内存管理。您的代码将没有泄漏的对象和内存崩溃。只需注意内存保留周期和变量所有权即可。
  2. 删除 NSMutableArray *_photoList;,您没有使用它,因为您将属性合成器声明为 @synthesize photoList;。此外,正如罗伯特在下面评论的那样,您应该在使用该属性时使用这种形式来明确区分:@synthesize photoList = photoList_;下划线放在最后更好,因为 Apple 在开头使用它,您不想不小心使用相同的变量名。

  3. 使用属性访问器来管理 ivar。而不是这样做:

    如果(照片列表 == 无)
    photoList = [[NSMutableArray alloc] init ];

试试这个:

if (photoList == nil)
self.photoList = [[[NSMutableArray alloc] init] autorelease];

在您的示例中,两行具有相同的行为,但第二行更可取,因为它将依赖于您的可变内存策略。如果你有一天通过副本或分配更改你的保留,你的代码仍然可以毫无问题地工作。以同样的方式,通过为你的 ivar 分配一个 nil 来释放你的内存 self.photoList = nil

为什么你认为你有泄漏的对象?

关于ios - 重新加载对象时 NSMutableArray 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11072382/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com