【问题标题】:EXC_BAD_ACCESS with UIBarButtonItem appearanceWhenContainedIn on iOS 7在 iOS 7 上带有 UIBarButtonItem 外观的 EXC_BAD_ACCESS
【发布时间】:2013-10-01 19:40:33
【问题描述】:
//Set all cancel buttons in search bars to "Done"
id searchBarButton = [UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil];
if([[[UIDevice currentDevice] systemVersion] floatValue] < 7) {
    [searchBarButton setTitle:@"Done"];
} else {
    //Can't do anything here or i get EXC_BAD_ACCESS
}

这在viewDidLoad 中调用时会给出 EXC_BAD_ACCESS,仅在 iOS 7 Gold Master 和更高版本上。 iOS 7 beta 6 及更早版本都可以。

在 iOS 7 中是否有其他方法可以做到这一点?

NSLog("%@", searchBarButton) 在 iOS7 上会产生这样的结果:

2013-10-01 16:14:25.972 MP Staging[12293:a0b] <_UIBarItemAppearance:0x1aaf72d0> <Customizable class: UIBarButtonItem> when contained in ( UISearchBar ) with invocations (null)>

这在 iOS 6 上

&lt;_UIBarItemAppearance: 0x1c671aa0&gt;

【问题讨论】:

    标签: ios ios7 uisearchbar exc-bad-access


    【解决方案1】:

    setTitle 在 iOS7 中会失败。

    试试下面来自this博客的代码:

    -(void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller{
        self.searchDisplayController.searchBar.showsCancelButton = YES;
        UIButton *cancelButton;
        UIView *topView = self.searchDisplayController.searchBar.subviews[0];
        for (UIView *subView in topView.subviews) {
            if ([subView isKindOfClass:NSClassFromString(@"UINavigationButton")]) {
                cancelButton = (UIButton*)subView;
            }
        }
        if (cancelButton) {
          //Set the new title of the cancel button
            [cancelButton setTitle:@"Annuller" forState:UIControlStateNormal];
        }
    }
    

    【讨论】:

    • 如果我在cancelButton = (UIButton*)subview 设置断点,它永远不会到达它
    • 我将self.searchDisplayController.searchBar 更改为self.venueSearchBar 并添加了一个断点。两个子视图类是UISearchBarBackgroundUISearchBarTextField
    • 好的,现在试试更新,你需要把这段代码放在searchDisplayControllerWillBeginSearchdelegate中。
    • 如果我将此代码放入searchDisplayControllerWillBeginSearch,它不起作用,但如果我将其放入searchDisplayControllerDidBeginSearch,它会显示“取消”一秒钟,然后淡入“完成”
    • 我将代码放入searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString,它实际上给了我想要的效果。在您开始输入之前,它会显示“取消”,然后在您开始输入时显示完成
    【解决方案2】:

    我在 7.1 中使用它没有任何问题,但是,它似乎在 7.0.x(设备和 sim)上崩溃了 - 希望这意味着他们已经在 7.1 中恢复了该属性,但这也意味着我们对于临时版本,必须使用上述子视图遍历黑客之一。

        id barButtonAppearanceInSearchBar = [UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil];
        [barButtonAppearanceInSearchBar setTitleTextAttributes:@{NSFontAttributeName:[UIFont fontWithName:@"HelveticaNeue" size:15],
                                                                 NSForegroundColorAttributeName : [UIColor blackColor]
                                                                 } forState:UIControlStateNormal];
        [barButtonAppearanceInSearchBar setTitle:@"Done"];
    

    【讨论】:

      【解决方案3】:

      UIBarButtonItemtitle 属性无法通过UIAppearance 代理使用。

      我不知道为什么它可以在 iOS 6 中运行,但绝对不应该这样。

      您似乎唯一的选择是“破解”UISearchBar,方法是爬取其子视图以查找按钮并设置标题,但是:

      • 非常脆弱,因为对子视图结构的任何实现更改都会破坏您的代码
      • 这不是全局的,您必须在任何 UISearchBar 实例上执行此操作

      根据this answer,您可以在UISearchDisplayDelegatesearchDisplayControllerWillBeginSearch: 方法中执行此“hack”,如下所示:

      - (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
           [theSearchBar setShowsCancelButton:YES animated:NO];
      
          UIButton *cancelButton;
          UIView *topView = theSearchBar.subviews[0];
          for (UIView *subView in topView.subviews) {
              if ([subView isKindOfClass:NSClassFromString(@"UINavigationButton")]) {
                  cancelButton = (UIButton*)subView;
              }
          }
          if (cancelButton) {
              [cancelButton setTitle:@"YourTitle" forState:UIControlStateNormal];
          }
      }
      

      【讨论】:

      • 那么在 ios6 和 ios7 上设置取消按钮文本的最佳做法是什么?
      • 如果我将此代码放入searchDisplayControllerWillBeginSearch,它不起作用,但如果我将其放入searchDisplayControllerDidBeginSearch,它会显示“取消”一秒钟,然后淡入“完成”
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      • 2013-12-27
      相关资源
      最近更新 更多