gpt4 book ai didi

ios - 导航栏中的 SearchController 问题

转载 作者:行者123 更新时间:2023-11-28 11:05:28 26 4
gpt4 key购买 nike

我正在尝试创建一个搜索栏,当您单击“搜索”(也在导航栏中)时,它会出现在导航栏的顶部。单击搜索结果会将您带到详细信息页面,搜索栏将在该页面消失。当您单击返回主页 VC 时,搜索栏会重新出现。以为这很简单,但遇到了一些问题。这是我到目前为止所做的

要在 HomeVC 中点击“搜索”时创建搜索栏,我这样做了:

@IBAction func SearchAction(sender: AnyObject) {
searchController.searchResultsUpdater = self
searchController.searchBar.delegate = self
definesPresentationContext = true
searchController.dimsBackgroundDuringPresentation = false
searchController.hidesNavigationBarDuringPresentation = false
self.navigationController?.presentViewController(searchController, animated: true, completion: nil)
}

第一个问题,当您转到详细信息页面时,搜索栏不会消失。

解决方案:在PrepareForSegue中,我添加了

self.searchController.searchBar.removeFromSuperview()

并用委托(delegate)替换了 unwindSegue,以便当用户从详细信息页面返回到 Home VC 时,搜索栏会重新添加。HomeVC 执行以下操作:

func didDismissDetail() {
self.navigationController?.popViewControllerAnimated(true)
if searchController.active == true {
self.navigationController?.view.addSubview(searchController.searchBar)
}
}

问题二:搜索的场景有bug,点击进入详情页面,返回首页VC,点击取消关闭搜索 Controller 。当您再次单击导航栏中的搜索按钮时,没有任何反应。我收到此错误:由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“应用程序试图以模态方式呈现事件 Controller 。”解决方案:我加了这个

func searchBarCancelButtonClicked(searchBar: UISearchBar) {
self.searchController.searchBar.removeFromSuperview()
}

然而,这有效,当 View 被移除时没有动画。抱歉,我知道这有点啰嗦 - 我的问题是:

  1. 有没有更好的方法来打造这种用户体验?
  2. 如果不是,您如何在用户点击“取消”时以动画方式移除搜索栏

    以下是一些图片:

Home Screen After clicking "Search"

最佳答案

而不是使用 self.searchController.searchBar.removeFromSuperview()你应该使用:

navigationController?.dismissViewControllerAnimated(true, completion: nil)`

关闭 View 。另外,你应该给你的 segue 一个标识符并在 prepareForSegue 中检查它。 .您的实现可能看起来像这样:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "ToDetail" {
let destination = segue.destinationViewController as! DetailViewController
navigationController?.dismissViewControllerAnimated(true, completion: nil)
//Pass Info to Detail View
}
}

然后在didSelectRowAtIndexPath只需使用 performSegueWithIdentifier 执行您的 segue .

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
performSegueWithIdentifier("ToDetail", sender: self)
}

要让搜索栏重新出现,您可以设置一个名为 searchBarShouldBeOpen 的 bool 变量在主视图 Controller 上。在你的SearchAction函数将这个值设置为true,然后在viewWillAppear使用带有 searchBarShouldBeOpen 的 if 语句决定是否运行 SearchAction .另外,考虑制作 SearchAction一个常规函数并将示例中显示的最后一行以外的所有内容移动到 viewDidLoad .最后,执行 UISearchBarDelegate为您的主视图 Controller 覆盖 searchBarCancelButtonClicked在里面设置 searchBarShouldBeOpen假的。您的主视图 Controller 看起来像这样:

class ViewController: UIViewController {
//...Your Variables

var searchBarShouldBeOpen: Bool = false

let searchBarKey = "SearchBarText"

override func viewDidLoad() {
super.viewDidLoad()
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
searchController.searchBar.delegate = self
searchController.hidesNavigationBarDuringPresentation = false

navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Search", style: .Plain, target: self, action: #selector(ViewController.showSearchBar))
}

override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
if searchBarShouldBeOpen {
navigationController?.presentViewController(searchController, animated: false, completion: nil)
searchBarShouldBeOpen = true
if let previousText = NSUserDefaults.standardUserDefaults().stringForKey(searchBarKey) {
searchController.searchBar.text = previousText
}
}
}

func showSearchBar() {
navigationController?.presentViewController(searchController, animated: true, completion: nil)
searchBarShouldBeOpen = true
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "ToDetail" {
let destination = segue.destinationViewController as! DetailViewController
if searchController.searchBar.text != "" {
NSUserDefaults.standardUserDefaults().setValue(searchController.searchBar.text, forKey: searchBarKey)
}
//Pass Info
}
}
//Your functions...
}

extension ViewController: UISearchBarDelegate {
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
searchBarShouldBeOpen = false
}
}

在你的细节 View Controller 中添加:

override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
navigationController?.dismissViewControllerAnimated(true, completion: nil)
}

编辑:

  1. 已更改 viewWillAppear手动呈现 UISearchBar没有动画而不是使用 showSearchBar这样它就不会每次都动画。

  2. 添加了对 super.viewWillAppear(animated) 的缺失调用

  3. 移动了对 UISearchBar 的解雇到 viewWillAppear详细 View Controller ,因此搜索不会在转场之前消失。

  4. 坚持 UISearchBar使用 NSUserDefaults 的文本(在 prepareForSegue 中)这样它就可以加载到 viewWillAppear 中将搜索设置为之前的内容。

  5. 添加了 searchBarKey常量用作 UISearchBar 的键文本持久性,因此不会使用“魔术字符串”来设置和访问保存的文本。

注意:您真的应该考虑使用 didSelectRowAtIndexPath执行转场。

其他选项:如果您想要 UISearchBar要在主视图 Controller 过渡到详细 View Controller 的同时进行动画处理,您可以使用自定义转场(这将使动画更流畅)。我制作了一个创建此效果的自定义 segue 示例。请注意,您必须将 Interface Builder 中的 View Controller 之间的转接更改为“自定义”类型,并且成为 UIStoryboardSegue 的以下子类。 .

class CustomSegue: UIStoryboardSegue {

override func perform() {
let pushOperation = NSBlockOperation()
pushOperation.addExecutionBlock {
self.sourceViewController.navigationController?.pushViewController(self.destinationViewController, animated: true)
}
pushOperation.addExecutionBlock {
self.sourceViewController.navigationController?.dismissViewControllerAnimated(true, completion: nil)
}
pushOperation.queuePriority = .Normal
pushOperation.qualityOfService = .UserInitiated
let operationQueue = NSOperationQueue.mainQueue()
operationQueue.addOperation(pushOperation)

}

}

您可以在以下链接中阅读有关自定义转场中代码的更多信息:

  1. 自定义转场:http://www.appcoda.com/custom-segue-animations/
  2. NSOperation:http://nshipster.com/nsoperation/

希望对您有所帮助!如果您需要详细说明,请询问! :)

关于ios - 导航栏中的 SearchController 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37979627/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com