UITableView被解除分配,而键值观察者仍然在其中注册

时间:2015-01-19 06:01:20

标签: ios objective-c uitableview

对于大多数具有侧边菜单功能的应用,我使用 MFSideMenu 控制器。所有应用程序在iOS 7及之前的版本上运行良好,但不适用于运行iOS 8的iPhone 6设备(在运行iOS8的iPhone 5上正常工作)。
我似乎无法弄清楚如何解决我收到的这个错误。单击LeftMenu UITableView上的单元格时,应用程序崩溃并发出此错误。

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'An instance 0x7fc492877e00 of class UITableView was deallocated while key value observers were still registered with it. Current observation info: <NSKeyValueObservationInfo 0x7fc492634860>

注意:UITableView是一个XIB IBOutlet

这就是代码的外观

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.

    // This will remove extra space on top of the tableview
    self.automaticallyAdjustsScrollViewInsets = NO;
    // This will remove extra separators from tableview
    self.tblViewMenu.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];

    // menu titles
    arrMenu = [Config returnArrLeftMenu];

    // check login status
    [self checkLoginStatus];
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CustomCellIdentifier = @"CustomCellIdentifier ";

MenuCell *mCell = (MenuCell *)[tableView dequeueReusableCellWithIdentifier: CustomCellIdentifier];

// menu cell
if (mCell == nil) {
    NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"MenuCell" owner:self options:nil];

    for (id oneObject in nib) if ([oneObject isKindOfClass:[MenuCell class]])
        mCell = (MenuCell *)oneObject;

}

    mCell.selectionStyle = UITableViewCellSelectionStyleBlue;
    mCell.contentView.backgroundColor = [UIColor clearColor];
    mCell.backgroundColor = [UIColor clearColor];
    mCell.lblTitle.text = [arrMenu objectAtIndex:indexPath.row];

    return mCell;
}


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    // load selected menu view on to the MAinViewController
    MainViewController *mainController = [[MainViewController alloc] initWithNibName:@"MainViewController" bundle:nil];

    mainController.title = [arrMenu objectAtIndex:indexPath.row];
    mainController.menuIndex = (int)indexPath.row;

    UINavigationController *navigationController = self.menuContainerViewController.centerViewController;
    NSArray *controllers = [NSArray arrayWithObject:mainController];
    navigationController.viewControllers = controllers;
    [self.menuContainerViewController setMenuState:MFSideMenuStateClosed];

}

3 个答案:

答案 0 :(得分:11)

您可能会使用以下代码观察TableView的属性更改:

[self.tblViewMenu addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:nil]

对观察者(您的类实例)的引用与不安全的未保留语义一起存储。您必须在dealloc()期间清理它以避免应用程序崩溃(ARC无法为您处理此问题)。

所以你的dealloc()应该取消注册这样的观察者:

- (void)dealloc {
    [self.tblViewMenu removeObserver:self forKeyPath:@"frame"];
}

您必须将“frame”替换为您感兴趣的属性的名称。

务必在正确的Apple Guide

中检查键值观察(KVO)的基本概念

修改

我刚检查了MFSideMenu的源代码。该代码中没有KVO使用的迹象,因此崩溃可能不是由该组件引起的。

答案 1 :(得分:4)

对于swift版本,您可以使用&#34; deinit&#34;删除所有观察者的方法

 deinit {
    self.yourtable.removeObserver(self, forKeyPath: "keyname")
}

答案 2 :(得分:0)

在取消分配控制器之前,您确定您的tableView实际上已正确清理吗?尝试向控制器添加-(void) dealloc{}方法并在其中添加断点。如果你的控制器在调用dealloc时仍然引用tableView,那么它将导致你看到的那种问题。

如果是这种情况,那么您需要覆盖removeFromParentViewController

控制器的方法并手动将tableView属性设置为nil。例如:

-(void) removeFromParentViewController {
    [super removeFromParentViewController];
    if(self.tableView!=nil) {
        self.tableView.delegate = nil;
        self.tableView.dataSource = nil;
        self.tableView = nil;
    }
}

希望有所帮助!