【问题标题】:Memory issue in iPhone OS (shorter version)iPhone OS 中的内存问题(较短版本)
【发布时间】:2009-10-07 01:42:33
【问题描述】:

我正面临某种我无法弄清楚的与内存相关的问题。

我有一个列出一些设置的摘要视图和一个可以编辑每个设置的详细视图。

在摘要视图中,我有一个由设置数组 (settingArray) 填充的表格视图,而这些设置又从核心数据存储库加载。

//  SettingsViewController.h
@interface SettingsViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
    NSMutableArray *settingArray;
}
@property (nonatomic, retain) NSMutableArray *settingArray;

//  SettingsViewController.m
- (void)viewWillAppear:(BOOL)animated {
    [self setSettingArray:[DataHelper searchObjectsInContext:@"Sections" :nil :@"Id" :YES :managedObjectContext]];
}

这个 NSManaged 对象数组用于为自定义 UITableViewCell 赋值,该 UITableViewCell 有两个标签:标题和描述。

//  SettingsViewController.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    […]
    [cell.titleLabel setText:[[settingArray objectAtIndex:indexPath.row] valueForKey:@"Title"]];    
    [cell.descriptionLabel setText:[[settingArray objectAtIndex:indexPath.row] valueForKey:@"Description"]];    
    […]
}

当用户点击一行时,这会加载一个详细视图,您可以在其中编辑值并将它们保存到数据库中。摘要视图向详细视图传递 NSManagedObject 引用(settingObject),以便了解核心数据数据库中的哪些记录被选中并且必须更新。

//  SettingsViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    if (settingsDetailViewController == nil) {
        settingsDetailViewController = [[SettingsDetailViewController alloc] initWithNibName:@"SettingsDetailView" bundle:nil];
    }

    // Pass corresponding settingArray object to detail view in the settingObject variable
    settingsDetailViewController.settingObject = [settingArray objectAtIndex:indexPath.row];
    […]
}

在详细视图中,用户可以修改一些值,然后将修改后的核心数据对象保存在数据库中。

//  SettingsDetailViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // Update current setting in database
    [self.settingObject setValue:[tableView cellForRowAtIndexPath:indexPath].textLabel.text forKey:@"Description"];
}

问题是,一旦在这个 NSManagedObject 的详细视图中更新了值,当重新加载摘要视图中的 tableview 信息时,我会在从 settingArray 读取标签信息的位置得到一个 EXC_BAD_ACCESS。

//  SettingsViewController.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    [cell.titleLabel setText:[[settingArray objectAtIndex:indexPath.row] valueForKey:@"Title"]];    

    // HERE IS WHERE THE ERROR OCCURS IN THE SECOND PASS
    [cell.descriptionLabel setText:[[settingArray objectAtIndex:indexPath.row] valueForKey:@"Description"]];    
    […]
}

我猜这与正在使用的 settingArray 或 settingObject 的释放有关,但我尝试了不同的方法,但还没有解决方案。所有变量都在相应的.h 中声明,属性使用nontoxic 和retain 添加,访问器在.m 中合成,对象在dealloc 函数中释放。根据 Cocoa 内存管理指南,它应该可以工作。

有趣的是,我的代码的其他部分使用相同的数组并毫无问题地传递相同的对象。

有什么提示吗?

【问题讨论】:

  • 我知道执行[DataHelper searchObjectsInContext:@"Sections" :nil :@"Id" :YES :managedObjectContext] 是有效的objective-c 语法,但是这很丑。这些参数到底是干什么用的?

标签: iphone memory core-data


【解决方案1】:

Clang 静态分析会发现很多引用计数错误,因此您不妨试一试。

您可以使用运行 -> 构建和分析手动运行它,也可以通过“运行静态分析器”构建设置为所有构建启用它。

请注意,此工具目前仅支持 C 和 Objective-C,但不支持 C++ / Objective-C++。

【讨论】:

    【解决方案2】:

    如果没有完整的来源,很难查明问题所在。 您可以尝试一些项目:

    • 确保 SettingsDetailViewController.h 中的“settingObject”属性声明为“retain”。也许你忘记了“retain”,而是在 dealloc 方法中释放了这个实例?
    • 尽量不要在 SettingsDetailViewController 中设置 settingObject 属性(并且不要在任何方法中使用它 - 只需注释掉这些部分)。如果这有所不同,则它必须与 SettingsDetailViewController 的此 settingObject 的保留/释放有关
    • 在 SettingsDetailViewController(调试器或 NSLog 语句)中跟踪 settingObject 对象的“retainCount”,在您使用它的位置以及在 dealloc 中释放它之后。这可能会给你一些线索

    【讨论】:

    • settingObject 是这样设置的: NSManagedObject *settingObject; @property (nonatomic, 保留) NSManagedObject *settingObject;如果我注释掉 SettingObject 的设置,问题就会消失,所以问题就是这样。跟踪 retainCount,我可以看到它最初设置为 5。奇怪的是,如果我单击另一个 tabBar 按钮并返回设置选项卡,错误似乎消失了,这意味着我可以返回摘要视图和 [单元格。 descriptionLabel setText..] 没有错误。但是,如果我再次单击某个设置并加载详细信息视图,则会再次出现错误。
    • 是否可以创建一个精简版的 xcode 项目,但仍然可以重现问题?如果您能以某种方式使其可供下载,以便我(或其他 SO 用户)可以尝试,那就太好了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多