【问题标题】:iOS 7 doesn't show cancel button of search bar in navigation bariOS 7 在导航栏中不显示搜索栏的取消按钮
【发布时间】:2013-09-28 15:16:44
【问题描述】:

在应该在 iOS 6 和 iOS 7 上运行的应用程序中,如果应用程序在 iOS 7 上运行,则嵌入在导航栏中的搜索栏的取消按钮不再显示。在 iOS 6 上,它可以工作。

搜索栏位于导航栏的标题视图中,如果搜索栏成为第一响应者,则应显示取消按钮:

iOS 7

iOS 6

在一个孤立的测试用例中,代码很简单:

@interface MyViewController : UITableViewController<UISearchBarDelegate>

@property (nonatomic) IBOutlet UISearchBar* searchBar;

@end


@implementation MyViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.navigationItem.titleView = self.searchBar;
}

- (void) searchBarTextDidBeginEditing: (UISearchBar*) searchBar {
    [searchBar setShowsCancelButton: YES animated: YES];
}

@end

这是我在文档中遗漏的 iOS 7 的故意更改吗?如果是,应该是什么替代方案?

如果没有,我的代码是否有错误?

【问题讨论】:

  • 你设置了 UISearchBar 的代理了吗?
  • 是的,我已经在 Interface Builder 中设置了委托,并按预期调用了 searchBarTextDidBeginEditing:。否则它将无法在 iOS 6 上运行。

标签: ios ios7 uisearchbar


【解决方案1】:

看起来您所做的一切都是正确的,但显然 Apple 在 iOS 7 中对某些方面进行了更改。According to this SO question 在 iOS 7 中,取消按钮不会出现在嵌入在 UINavigationBar 中的 UISearchBar 上。

根据developer documentationshowsCancelButton 属性的效果可能与setShowsCancelButton:Animated 方法略有不同。尝试这样做:

searchBar.showsCancelButton = YES;
[searchBar setShowsCancelButton:YES animated:YES];

我不确定这是否会产生任何影响。您也可以尝试将代码放在不同的委托方法中:

- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar; // return NO to not become first responder
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar; // called when text starts editing

您可能还想查看iOS 7 changelog。看起来 Apple 在添加到 UINavigationBar 时更改了行为或 UISearchDisplayController / UISearchBar。看看 UIKit 部分下的最后一个要点(虽然不清楚具体发生了什么变化)。


您可能还想尝试使用UISerachDisplayController。更简单的方法是将UISearchBar 嵌入UITableView 的标题中。

【讨论】:

  • “showsCancelButton 属性与 setShowsCancelButton:Animated 方法不同” - 您在文档中的什么地方看到的?该方法是一种用动画设置属性的方法。
  • 感谢您提出的所有想法。我无法确认 showsCancelButtonsetShowsCancelButton:animated: 不相关。如果我使用您的代码,iOS 7 上的问题仍然存在,iOS 6 上的动画不再起作用。将代码移动到不同的委托方法也没有任何效果。 iOS 7 更新日志中的最后一个要点是我知道的一项改进,但它不会影响我的问题,因为我没有使用 UISearchDisplayController
  • 您最好的提示是参考其他 SO 问题。这样,取消按钮就会出现。但是,搜索栏样式的更改和搜索栏的适当大小将需要一些额外的努力。如果搜索栏嵌入在导航栏中,它确实看起来好像故意表现得不同。了解这种变化背后的想法会很有趣。
  • 我接受您的回答,因为它包含最相关的信息。然而,我确实走了一条不同的路线:在 iOS 7 中,我现在将搜索栏添加到我的表格视图的标题中(而不是导航栏)。这似乎是使取消按钮可见的最简单方法。我也尝试使用 UISearchDisplayController,但它有太多问题(例如,如果表格视图没有滚动到最顶部,则会忽略点击)。
【解决方案2】:

我已经简单地解决了这个问题,只需添加 rightBarButtonItem :)

self.navigationItem.titleView = self.searchBar;
self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Cancel", nil) style:UIBarButtonItemStylePlain target:self action:@selector(didClickCancelButton:)] autorelease];

但请务必检查当前 iOS 版本是否 >= 7.0,否则您将获得两个“取消”按钮..

顺便说一句,此方法允许您拥有始终启用的“取消”按钮

【讨论】:

  • 我喜欢这个答案。它使事情变得简单,不会试图与内置行为作斗争,而是让您完全控制。
  • 简洁优雅。好主意!
【解决方案3】:

iOS 7 和 iOS 6 的导航栏不同,所以如果你想在导航栏中显示 UISearch bar,你可以试试这个:

将您的 UISearchbar 放在 UIView 上,例如 this[self.searchView addSubview self.searchBar],并将导航栏的 titleView 设置为您的 searchView,例如 thisself.navagitioncontroller.navigationItem.titleView = self.searchView

希望对你有用

【讨论】:

    【解决方案4】:

    如果您将 UISearchBar 与 UISearchDisplayController 一起使用,您可以在“searchDisplayControllerWillBeginSearch”委托方法中简单地设置取消按钮以显示,如下所示:(iOS 7 测试)

    -(void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller{
        controller.searchBar.showsCancelButton = YES;
    }
    

    【讨论】:

    • 如果 UISearchBar 位于导航栏中,则不显示取消按钮。 UISearchDisplayController 在这里没有帮助。如果将 UISearchBar 放在 UITableView 的标题中并与 UISearchDisplayController 结合使用,则会显示取消按钮,但如果 UITableView 的滚动视图未位于最顶部,则它不会对点击事件做出反应。有点乱。
    【解决方案5】:

    iOS6 和 iOS7 之间似乎确实存在变化,从 xxxDidYYY 方法对 UI 的更改有时不起作用,您必须在 xxxWillYYY 方法或从主事件循环(例如,在一个块中或在短暂的延迟之后)。

    在你的情况下,试试这个:

    - (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar
    {
        searchBar.showsCancelButton = YES;
        return YES;
    }
    

    【讨论】:

    • 我试过你的代码,但它没有改变任何东西。即使我将搜索栏配置为始终显示取消按钮,它也不会显示。所以问题似乎与使用的委托方法无关。
    【解决方案6】:

    在我看来,这是一个错误。这是我的解决方法。它并不完美,但它适用于 iOS 6 和 7。在 iOS7 上,搜索栏文本字段在淡出时滑过取消按钮,而在 iOS6 上,文本字段宽度扩展没有动画效果。

    @interface FTViewController ()
    @property(nonatomic, strong) UISearchBar *searchBar;
    @end
    
    @implementation FTViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        self.searchBar = [[UISearchBar alloc] init];
        self.searchBar.delegate = self;
    
        if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_6_1) {
            // iOS 6.1 and older (only tested on 6.1)
            [self.searchBar sizeToFit];
            self.searchBar.backgroundImage = nil;
        }
    
        self.navigationItem.titleView = self.searchBar;
    }
    
    -(void)cancelBarButtonItemClicked:(id)sender
    {
        [self searchBarCancelButtonClicked:self.searchBar];
    }
    
    -(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
    {
        [searchBar resignFirstResponder];
        [self.navigationItem setRightBarButtonItem:nil animated:YES];
    }
    
    -(BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar
    {
        UIBarButtonItem *cancelBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelBarButtonItemClicked:)];
        [self.navigationItem setRightBarButtonItem:cancelBtn animated:YES];
    
        return YES;
    }
    @end
    

    【讨论】:

      【解决方案7】:

      有两种选择:

      1. 向 uiviewcontroller.view 添加搜索栏(如子视图)并在需要时隐藏导航栏
      2. 在 uiviewcontroller.navigationItem.rightBarButtonItem 中添加取消按钮

      我更喜欢第二个,但第一个看起来更原生。

      【讨论】:

      • 因为我还有其他需要显示的导航栏按钮项目,所以我选择了选项 2。
      【解决方案8】:

      这确实是一个从 7.1 开始修复的错误。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多