使用 UISearchBar 方法导致 EXC_BAD_ACCESS 崩溃

发布于 2024-12-03 13:32:47 字数 4018 浏览 1 评论 0原文

我有一个 UISearchBar 设置,当使用它时,它有一个覆盖灰色视图的覆盖层,类似于苹果的做法。

当我单击这个变暗的视图时,它会退出搜索模式,这很好,但是当我再次搜索,然后再次单击灰色退出时,它会因 EXC BAD ACCESS 错误而崩溃。

以下是一些相关代码:

在此处输入图像描述

崩溃始终发生在 [rvController didSearching_Clicked:nil];< /code>

OverlayViewController.h

@interface OverlayViewController : UIViewController

@property (nonatomic, retain) ChooserViewController *rvController;
@property (nonatomic, retain) CPTViewController *cptViewController;


@implementation OverlayViewController

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    [rvController doneSearching_Clicked:nil];
    [cptViewController doneSearching_Clicked:nil];
}

- (void) dealloc {
    [rvController release];
    [cptListViewController release];
    [super dealloc];
}

@end

带搜索栏的实际 VC 代码

- (void) searchBarSearchButtonClicked:(UISearchBar *)theSearchBar
{
    searching = YES;
    [ovController.view removeFromSuperview];
    letUserSelectRow = YES;
    self.tableView.scrollEnabled = YES;
    if (self.mySearchBar.text !=nil)
    {
        NSPredicate *predicate =[NSPredicate predicateWithFormat:@"(name contains[cd] %@) OR (code contains[cd] %@)", self.mySearchBar.text, self.mySearchBar.text];
        [fetchedResultsController.fetchRequest setPredicate:predicate];
    }
    else
    {
        NSPredicate *predicate =[NSPredicate predicateWithFormat:@"All"];
        [fetchedResultsController.fetchRequest setPredicate:predicate];
    }

    NSError *error = nil;
    if (![[self fetchedResultsController] performFetch:&error]) 
    {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        exit(-1);  // Fail
    } 

    self.searchArray = fetchedResultsController.fetchedObjects;

    [mySearchBar resignFirstResponder];

    [self.tableView reloadData];
}

- (void) searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
    self.navigationItem.leftBarButtonItem = nil;

    if(searching)
        return;

    if(ovController == nil)
        ovController = [[OverlayViewController alloc] initWithNibName:@"OverlayView" bundle:[NSBundle mainBundle]];

    CGFloat yaxis = self.navigationController.navigationBar.frame.size.height;
    CGFloat width = self.view.frame.size.width;
    CGFloat height = self.view.frame.size.height;

    CGRect frame = CGRectMake(0, yaxis, width, height);
    ovController.view.frame = frame;    
    ovController.view.backgroundColor = [UIColor grayColor];
    ovController.view.alpha = 0.5;

    ovController.rvContrller = self;

    [self.tableView insertSubview:ovController.view aboveSubview:self.parentViewController.view];

    searching = YES;
    letUserSelectRow = NO;
    self.tableView.scrollEnabled = NO;

    self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] 
                                               initWithBarButtonSystemItem:UIBarButtonSystemItemCancel 
                                               target:self action:@selector(doneSearching_Clicked:)] autorelease];
}

- (void) searchBarTextDidEndEditing:(UISearchBar *)searchBar
{
    searchBar.showsCancelButton = NO;
}

- (void)searchBar:(UISearchBar *)theSearchBar textDidChange:(NSString *)searchText 
{
    [self.tableView insertSubview:ovController.view aboveSubview:self.parentViewController.view];

    searching = NO;
    letUserSelectRow = NO;
    self.tableView.scrollEnabled = NO;

    [self.tableView reloadData];
}
- (void) doneSearching_Clicked:(id)sender {

    mySearchBar.text = @"";
    [mySearchBar resignFirstResponder];

    letUserSelectRow = YES;
    searching = NO;
    self.navigationItem.rightBarButtonItem = nil;
    self.tableView.scrollEnabled = YES;

    [ovController.view removeFromSuperview];
    [ovController release];
    ovController = nil;

    [self.tableView reloadData];
    [self.tableView scrollToRowAtIndexPath:0 atScrollPosition:UITableViewScrollPositionTop animated:YES];
}

I have a UISearchBar setup and when its being used, it has an overlay grey view that covers the rest of the table similar to how apple does it.

When I click this darkened view, it exits search mode, which is good, but when I search again, then again click the grey to exit, it crashes with EXC BAD ACCESS error.

Here is some related code:

enter image description here

The crash is always at [rvController doneSearching_Clicked:nil];

OverlayViewController.h

@interface OverlayViewController : UIViewController

@property (nonatomic, retain) ChooserViewController *rvController;
@property (nonatomic, retain) CPTViewController *cptViewController;


@implementation OverlayViewController

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    [rvController doneSearching_Clicked:nil];
    [cptViewController doneSearching_Clicked:nil];
}

- (void) dealloc {
    [rvController release];
    [cptListViewController release];
    [super dealloc];
}

@end

Code for the actual VC with the search bar

- (void) searchBarSearchButtonClicked:(UISearchBar *)theSearchBar
{
    searching = YES;
    [ovController.view removeFromSuperview];
    letUserSelectRow = YES;
    self.tableView.scrollEnabled = YES;
    if (self.mySearchBar.text !=nil)
    {
        NSPredicate *predicate =[NSPredicate predicateWithFormat:@"(name contains[cd] %@) OR (code contains[cd] %@)", self.mySearchBar.text, self.mySearchBar.text];
        [fetchedResultsController.fetchRequest setPredicate:predicate];
    }
    else
    {
        NSPredicate *predicate =[NSPredicate predicateWithFormat:@"All"];
        [fetchedResultsController.fetchRequest setPredicate:predicate];
    }

    NSError *error = nil;
    if (![[self fetchedResultsController] performFetch:&error]) 
    {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        exit(-1);  // Fail
    } 

    self.searchArray = fetchedResultsController.fetchedObjects;

    [mySearchBar resignFirstResponder];

    [self.tableView reloadData];
}

- (void) searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
    self.navigationItem.leftBarButtonItem = nil;

    if(searching)
        return;

    if(ovController == nil)
        ovController = [[OverlayViewController alloc] initWithNibName:@"OverlayView" bundle:[NSBundle mainBundle]];

    CGFloat yaxis = self.navigationController.navigationBar.frame.size.height;
    CGFloat width = self.view.frame.size.width;
    CGFloat height = self.view.frame.size.height;

    CGRect frame = CGRectMake(0, yaxis, width, height);
    ovController.view.frame = frame;    
    ovController.view.backgroundColor = [UIColor grayColor];
    ovController.view.alpha = 0.5;

    ovController.rvContrller = self;

    [self.tableView insertSubview:ovController.view aboveSubview:self.parentViewController.view];

    searching = YES;
    letUserSelectRow = NO;
    self.tableView.scrollEnabled = NO;

    self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] 
                                               initWithBarButtonSystemItem:UIBarButtonSystemItemCancel 
                                               target:self action:@selector(doneSearching_Clicked:)] autorelease];
}

- (void) searchBarTextDidEndEditing:(UISearchBar *)searchBar
{
    searchBar.showsCancelButton = NO;
}

- (void)searchBar:(UISearchBar *)theSearchBar textDidChange:(NSString *)searchText 
{
    [self.tableView insertSubview:ovController.view aboveSubview:self.parentViewController.view];

    searching = NO;
    letUserSelectRow = NO;
    self.tableView.scrollEnabled = NO;

    [self.tableView reloadData];
}
- (void) doneSearching_Clicked:(id)sender {

    mySearchBar.text = @"";
    [mySearchBar resignFirstResponder];

    letUserSelectRow = YES;
    searching = NO;
    self.navigationItem.rightBarButtonItem = nil;
    self.tableView.scrollEnabled = YES;

    [ovController.view removeFromSuperview];
    [ovController release];
    ovController = nil;

    [self.tableView reloadData];
    [self.tableView scrollToRowAtIndexPath:0 atScrollPosition:UITableViewScrollPositionTop animated:YES];
}

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

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

发布评论

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

评论(2

欲拥i 2024-12-10 13:32:47
/// @OverlayView
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    [rvController doneSearching_Clicked:nil]; ///< Point 1
    [cptViewController doneSearching_Clicked:nil];
}

/// @VC Search bar
- (void) doneSearching_Clicked:(id)sender {

    mySearchBar.text = @"";
    [mySearchBar resignFirstResponder];

    letUserSelectRow = YES;
    searching = NO;
    self.navigationItem.rightBarButtonItem = nil;
    self.tableView.scrollEnabled = YES;

    /// Point 2 
    [ovController.view removeFromSuperview];
    [ovController release];
    ovController = nil;

    [self.tableView reloadData];
    [self.tableView scrollToRowAtIndexPath:0 atScrollPosition:UITableViewScrollPositionTop animated:YES];
}

Point 1处,它会调用-(void)doneSearching_Clicked,然后执行Point 2。在Point 2处,我认为OverlayView对象的retainCount将为0,这意味着它将被释放。因此,OverlayView 拥有的所有指针都可能无效,因为它在 -(void)dealloc 中释放了这些对象。根据你的代码,我只能知道这些。

编辑:
上述过程可以翻译为以下格式。 -doneSearching_Click 将导致[self release] 行为。

/// @OverlayView
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    [rvController doneSearching_Clicked:nil]; ///< Point 1
    /// [self release];  /// the above method will do such thing.
    [cptViewController doneSearching_Clicked:nil];
}
/// @OverlayView
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    [rvController doneSearching_Clicked:nil]; ///< Point 1
    [cptViewController doneSearching_Clicked:nil];
}

/// @VC Search bar
- (void) doneSearching_Clicked:(id)sender {

    mySearchBar.text = @"";
    [mySearchBar resignFirstResponder];

    letUserSelectRow = YES;
    searching = NO;
    self.navigationItem.rightBarButtonItem = nil;
    self.tableView.scrollEnabled = YES;

    /// Point 2 
    [ovController.view removeFromSuperview];
    [ovController release];
    ovController = nil;

    [self.tableView reloadData];
    [self.tableView scrollToRowAtIndexPath:0 atScrollPosition:UITableViewScrollPositionTop animated:YES];
}

At the Point 1, it will call -(void)doneSearching_Clicked, then it will execute Point 2. At Point 2, I think the OverlayView object's retainCount will be 0, that means it will deallocated. So, all pointers the OverlayView has may be invalid, because it releases those objects in -(void)dealloc. According to your codes, that is all I can know.

Edit:
The above procedures may be translated as following format. The -doneSearching_Click will result in [self release] behavior.

/// @OverlayView
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    [rvController doneSearching_Clicked:nil]; ///< Point 1
    /// [self release];  /// the above method will do such thing.
    [cptViewController doneSearching_Clicked:nil];
}
原来是傀儡 2024-12-10 13:32:47

您的代码并不完全是不言自明的,但我猜您过度释放了 ovController。您位于 ovControllertouchesBegan: 方法中,然后让它执行不同对象 rvContller 中的方法,该对象 释放调用对象。当尝试从方法调用返回到已释放的控制器时,您会收到错误访问错误。

Your code is not completely self explanatory, but I would guess that you are over-releasing ovController. You are in the ovController's touchesBegan: method, then you have it execute a method in a different object, rvContrller, which releases the calling object. When trying to return from the method call to the released controller you get the bad-access error.

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