EXC_BAD_ACCESS - NSFetchedResultsController、UITableViewController、UINavigationController、UIPopoverController

发布于 2024-12-26 19:16:25 字数 3667 浏览 3 评论 0原文

我在 UINavigationController 内有一个 UITableViewController,在 UIPopoverController 内。

UITableViewController 使用 NSFetchedResultsControllerdidSelectRowAtIndexPath 将我的 UITableViewController 的另一个实例推送到导航控制器堆栈上,该实例的谓词略有不同

如果我将一个新的 UITableViewController 推入堆栈,然后再次弹出它,如果我尝试保存一个会更新 tableview 的对象,我最终会得到一个 EXC_BAD_ACCESS那被弹出了。

正如预期的那样,将我的 NSFetchedResultsController 的委托设置为 nil 可以消除 EXC_BAD_ACCESS 错误。

我正在使用ARC。很明显,这些对象正在被释放。这没关系。但为什么当有变化时他们仍然会收到通知?

代码如下。我基本上是在数据库中跟踪网络视图的历史记录。

BookmarkViewController * bookmarkController = [[BookmarkViewController alloc] initWithStyle:UITableViewStylePlain andWebView:self.webView];
UINavigationController * bookmarkNavController = [[UINavigationController alloc] initWithRootViewController:bookmarkController];
self.bookmarkPopover = [[UIPopoverController alloc] initWithContentViewController:bookmarkNavController];
_bookmarkPopover.popoverContentSize = CGSizeMake(320, 44*10);
_bookmarkPopover.delegate = self;
bookmarkController.container=_bookmarkPopover;
bookmarkController.delegate=self;

BookmarkViewController 使用 NSFetchedResultsController,而 BookmarkViewControllerNSFetchedResultsController委托

- (NSFetchedResultsController *) myFetchedResultsController
{   
    if (self.fetchedResultsController != nil) {
        return self.fetchedResultsController;
    }   
    // Singleton
    CoreDataManager * dataManager = [CoreDataManager defaultDataManager];

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Bookmark" inManagedObjectContext:dataManager.managedObjectContext];
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"label" ascending:NO];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];

    [fetchRequest setEntity:entity];
    [fetchRequest setPredicate:self.predicate];
    [fetchRequest setSortDescriptors:sortDescriptors]; 
    [fetchRequest setFetchBatchSize:20]; // Set the batch size to a suitable number.

    self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                                                    managedObjectContext:dataManager.managedObjectContext
                                                                      sectionNameKeyPath:@"type"
                                                                               cacheName:nil];
    self.fetchedResultsController.delegate = self;

    return self.fetchedResultsController;
}

我还有:

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {    
    [self.tableView beginUpdates];
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView endUpdates];
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    BookmarkViewController * bookmarkViewController = [[BookmarkViewController alloc] initWithStyle:self.tableView.style 
                                                                                         andWebView:self.webview 
                                                                                          forFolder:bookmark.label];
    [self.navigationController pushViewController:bookmarkViewController animated:YES];
}

I have a UITableViewController inside a UINavigationController, inside a UIPopoverController.

The UITableViewController uses a NSFetchedResultsController. didSelectRowAtIndexPath pushes another instance of my UITableViewController with a slightly different predicate onto the nav controller stack.

If I push a new UITableViewController on to the stack, and then pop it again, I will eventually get a EXC_BAD_ACCESS if I try to save an object that would have updated the tableview that was popped off.

As expected, setting the delegate of my NSFetchedResultsController to nil removes the EXC_BAD_ACCESS errors.

I am using ARC. So clearly these objects are getting released. This is OK. But why are they still getting notified when there is a change?

Code below. I am basically tracking the history of a web view in my database.

BookmarkViewController * bookmarkController = [[BookmarkViewController alloc] initWithStyle:UITableViewStylePlain andWebView:self.webView];
UINavigationController * bookmarkNavController = [[UINavigationController alloc] initWithRootViewController:bookmarkController];
self.bookmarkPopover = [[UIPopoverController alloc] initWithContentViewController:bookmarkNavController];
_bookmarkPopover.popoverContentSize = CGSizeMake(320, 44*10);
_bookmarkPopover.delegate = self;
bookmarkController.container=_bookmarkPopover;
bookmarkController.delegate=self;

The BookmarkViewController uses an NSFetchedResultsController and BookmarkViewController is the delegate of the NSFetchedResultsController.

- (NSFetchedResultsController *) myFetchedResultsController
{   
    if (self.fetchedResultsController != nil) {
        return self.fetchedResultsController;
    }   
    // Singleton
    CoreDataManager * dataManager = [CoreDataManager defaultDataManager];

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Bookmark" inManagedObjectContext:dataManager.managedObjectContext];
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"label" ascending:NO];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];

    [fetchRequest setEntity:entity];
    [fetchRequest setPredicate:self.predicate];
    [fetchRequest setSortDescriptors:sortDescriptors]; 
    [fetchRequest setFetchBatchSize:20]; // Set the batch size to a suitable number.

    self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                                                    managedObjectContext:dataManager.managedObjectContext
                                                                      sectionNameKeyPath:@"type"
                                                                               cacheName:nil];
    self.fetchedResultsController.delegate = self;

    return self.fetchedResultsController;
}

And also I have:

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {    
    [self.tableView beginUpdates];
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView endUpdates];
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    BookmarkViewController * bookmarkViewController = [[BookmarkViewController alloc] initWithStyle:self.tableView.style 
                                                                                         andWebView:self.webview 
                                                                                          forFolder:bookmark.label];
    [self.navigationController pushViewController:bookmarkViewController animated:YES];
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

野侃 2025-01-02 19:16:25

我发现了一些相关问题:

已释放视图由于获取的结果控制器更新,控制器导致 EXC_BAD_ACCESS

如果我发布,我的访问权限会很差,如果我保留,我泄漏

第二个链接给了我在 dealloc 方法中将委托设置为 nil 的想法

-(void) dealloc
{
    self.fetchedResultsController.delegate = nil;
}

,但我使用的是 ARC,所以我无法显式调用 [super dealloc] 。似乎可以解决问题,但我不确定这是否正确。我是否还应该将其余的局部变量设置为nil?如果这覆盖了编译器生成的内容,它会泄漏吗?

I found some related questions:

Deallocated view controller causing EXC_BAD_ACCESS because of fetched results controller update

If I release, I get bad access, if I retain, I leak

The 2nd link gave me the idea of setting the delegate to nil in the dealloc method

-(void) dealloc
{
    self.fetchedResultsController.delegate = nil;
}

But I am using ARC so I cannot call [super dealloc] explicitly. Appears to fix the problem, but I am not sure this is correct. Should I also set the rest of my local variables to nil? If this overrides what ever the compiler generates, will it leak?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文