【问题标题】:Crash when calling setRightBarButtonItems:animated: multiple times, why?调用 setRightBarButtonItems:animated: 多次时崩溃,为什么?
【发布时间】:2014-10-24 21:45:53
【问题描述】:

我有两种方法可以在视图控制器的 UINavigationItem 中切换右栏按钮项。它基本上是在点击搜索按钮时在导航栏中显示一个搜索栏,并在用户执行搜索时隐藏搜索栏

- (void)displaySearchUI
{
    [self.mainNavigationController.topViewController.navigationItem setRightBarButtonItems:[self searchOpenItems] animated:YES];
    [self.searchBar becomeFirstResponder];
}

- (void)dismissSearchUI
{
    [self.mainNavigationController.topViewController.navigationItem setRightBarButtonItems:[self searchClosedItems] animated:YES];
}

- (NSArray *)searchClosedItems
{
    return @[[self someCustomItem],
             [self someOtherItem],
             [self searchButtonItem],
             ];
}

- (NSArray *)searchOpenItems
{
    return @[[self someCustomItem],
             [self someOtherItem],
             [self searchBarItem],
             ];
}

从 searchButtonItem 返回的项目使用带有图像的 UIBarButtonItem,而从 searchBarItem 返回的项目具有 UISearchBar 的自定义视图。每个搜索状态中的其他项目都是相同的。

当我调用 displaySearchUI 时,成为第一响应者的搜索栏会打开一个弹出窗口以显示一些搜索建议。当弹出框被用户关闭时,通过 popoverControllerDidDismissPopover: 委托方法调用dismissSearchUI。然而此时,应用程序通常会在 UINavigationBar 中遇到崩溃:

-[CALayer enumerateObjectsUsingBlock:]: unrecognized selector sent to instance 0x7de9ac80
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[CALayer enumerateObjectsUsingBlock:]: unrecognized selector sent to instance 0x7de9ac80'
*** First throw call stack:
(
    0   CoreFoundation                      0x056f0946 __exceptionPreprocess + 182
    1   libobjc.A.dylib                     0x05379a97 objc_exception_throw + 44
    2   CoreFoundation                      0x056f85c5 -[NSObject(NSObject) doesNotRecognizeSelector:] + 277
    3   CoreFoundation                      0x056413e7 ___forwarding___ + 1047
    4   CoreFoundation                      0x05640fae _CF_forwarding_prep_0 + 14
    5   UIKit                               0x03ba38aa -[UINavigationBar _setLeftViews:rightViews:] + 3774
    6   UIKit                               0x03b8f77e -[UINavigationItem updateNavigationBarButtonsAnimated:] + 186
    7   UIKit                               0x03b901a0 -[UINavigationItem setObject:forLeftRightKeyPath:animated:] + 600
    8   UIKit                               0x03b9100a -[UINavigationItem setRightBarButtonItems:animated:] + 104
    9   MyApp                               0x0028088b -[DisplayManager dismissSearchUI] + 283

我不确定这里到底会发生什么。无论设置项目是否为动画,似乎都会发生。它也只发生在用户在弹出框外点击时。如果我以编程方式解除弹出框并调用dismissSearchUI,则不会发生崩溃(我想是由于动画发生的顺序不同,或者由于用户解除弹出框与编程解除时UI中的某些状态差异。我已经试图通过这样做来解决它:

#pragma mark - UIPopoverControllerDelegate

- (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
    [self dismissSearchSuggestionsUI];
    return NO;
}

- (void)dismissSearchSuggestionsUI
{
    [self.popoverController dismissPopoverAnimated:YES];
    [self.displayManager dismissSearchUI];
}

但是我在这里得到了一个 EXC_BAD_ACCESS 崩溃,(有一个类似的堆栈跟踪让我相信这是同一个问题,只是由于时间问题而出现了不同的症状)。

有没有人遇到过这样的事情,有没有办法解决这个问题,而不必完全禁用手动用户弹出框解雇?

【问题讨论】:

    标签: ios objective-c cocoa-touch uinavigationbar uipopovercontroller


    【解决方案1】:

    呸,发帖后我就明白了。通过修改dismissSearchUI的方法来做到这一点:

    - (void)dismissSearchUI
    {
        [self.searchBar resignFirstResponder]
        [self.mainNavigationController.topViewController.navigationItem setRightBarButtonItems:[self searchClosedItems] animated:YES];
    }
    

    我解决了这个问题。我认为当用户执行搜索时,搜索栏会放弃自己的第一响应者,但是当用户手动取消搜索时,这不会自动发生,这会导致它所在的栏按钮项目从导航栏中删除。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-28
      • 2019-10-29
      • 1970-01-01
      • 2011-04-17
      • 1970-01-01
      相关资源
      最近更新 更多