iphone - 以特定方法访问NSManagedObjects时,应用程序崩溃

标签 iphone objective-c core-data crash

我在iPhone应用程序的UIViewController中(在UINavigationController中)有一个方法,只要在ViewController的 View 的表中选择了一行,就会调用该方法。在这种方法中,我访问存储在实例字段dreamsArray中的“Dream”数组,该实例字段包含数据库中的NSManagedObjects。我可以使用其他方法访问此数组中的对象,但是似乎每当我尝试使用此特定方法从此数组中检索或修改检索到的对象时,程序就会崩溃。

这是dreamsArray的创建方式:

    dreamsArray = [[NSMutableArray alloc] init];

    [self managedObjectContext];

    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Dream" inManagedObjectContext:managedObjectContext];
    [request setEntity:entity];

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"title" ascending:NO];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
    [request setSortDescriptors:sortDescriptors];
    [sortDescriptors release]; [sortDescriptor release];

    NSError *error;
    NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
    if ( mutableFetchResults == nil )
        NSLog(@"oh noes! no fetch results DreamsTabController:45");

    dreamsArray = [mutableFetchResults mutableCopy];
    [mutableFetchResults release];
    [request release];

查询dreamsArray及其对象的实例:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *cellID = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
    if ( cell == nil )
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID] autorelease];

    Dream *dream = (Dream *)[dreamsArray objectAtIndex:indexPath.row];

    cell.textLabel.text = [dream title];
    cell.detailTextLabel.text = @"foo!";

    [dream release];

    return cell;
}

还有所有问题的方法:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    Dream *dream = (Dream *)[dreamsArray objectAtIndex:indexPath.row];
    // BOOM - crashes right here
    EditDreamController *edit = [[EditDreamController alloc] initWithNibName:@"EditDream" bundle:nil];
    edit.dream = [[NSArray alloc] initWithObjects:dream.dreamContent, nil];
    [navigationController pushViewController:edit animated:YES];
    [dream release];
    [edit release];
}

查询dreamsArray后,应用程序立即崩溃。

即使在此方法中调用简单的NSLog(@"%@", dream.title)也会导致崩溃。这里可能出什么问题了?

最佳答案

以下代码更短,更高效,更易于阅读,并且没有第一个块的六个左右的内存泄漏:

NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:@"Dream" inManagedObjectContext:[self managedObjectContext]]];

static NSArray *sortDescriptors = nil;
if (!sortDescriptors)
    sortDescriptors = [[NSArray alloc] initWithObject:[[[NSSortDescriptor alloc] initWithKey:@"title" ascending:NO] autorelease]];
[request setSortDescriptors:sortDescriptors];

NSError *error = nil;
NSArray *fetchResults = [managedObjectContext executeFetchRequest:request error:&error];
if (!fetchResults)
    NSLog(@"oh noes! no fetch results DreamsTabController:45, error %@", error);
[request release];

dreamsArray = [NSMutableArray arrayWithArray:fetchResults];

将此方法重写为较小的示例,而不是过分释放梦想,这将导致崩溃:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
{
    static NSString *cellID = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID] ? : [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID] autorelease];

    Dream *dream = [dreamsArray objectAtIndex:indexPath.row];
    cell.textLabel.text = dream.title;
    cell.detailTextLabel.text = @"foo!";

    return cell;
}

该方法过分释放了“dream”,并在NSArray上发生了泄漏,因此也出现了“dream”实例。
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
{
    EditDreamController *editDreamController = [[EditDreamController alloc] initWithNibName:@"EditDream" bundle:nil];

    Dream *dream = [dreamsArray objectAtIndex:indexPath.row];
    editDreamController.dream = [NSArray arrayWithObjects:dream.dreamContent];

    [navigationController pushViewController:editDreamController animated:YES];
    [editDreamController release];
}

尚不清楚EditDreamController上的实例变量在获取数组时是单数的-如果确实可以设置多个变量,则应该是“梦想”。

-会

关于iphone - 以特定方法访问NSManagedObjects时,应用程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1449897/

相关文章:

iphone - 如何平铺 UIWebView?

ios - YTPlayerView 并不总是全屏

objective-c - 核心数据 : Traverse managed objects relationships with an abstract entity in-between

iphone - 为 iPad 和 iPhone 设计输入按钮

ios - UIButton 高度增加大小使用 AutoLayout 与不同的设备

iphone - Xcode 4. 3's ' 估计的应用程序商店大小与 .ipa 文件有很大不同,为什么?

objective-c - 在 obj-c 的数组中设置一个值

ios - 找不到 XCTest/XCTest.h 文件 XCode 5.1.1 iOS7

ios - 使用 xcode 7.2 永远编译模型文件

objective-c - 核心数据 : model is nil while modelURL is valid