在UITableView中使用UISearchController,在单元格选择上使用unwind segue

时间:2016-04-22 09:42:36

标签: ios uitableview swift2 uisearchcontroller unwind-segue

我有一个 UITableViewController ,它有一个向下钻取到显示大型数据集的另一个 UITableViewController 的单元格。为了提高可用性,我在视图中添加了 UISearchController 。搜索完成后,用户应单击该单元格,该单元格使用展开segue将用户返回到原始视图控制器,以恢复其数据。还有一个嵌入式导航器,可以帮助导航。

如果我没有执行搜索并只是单击它正确展开的单元格并填充原始单元格中的选择,但如果我进行搜索然后选择一个单元格,则会出现以下错误:

popToViewController:transition:在发生现有转换或演示时调用;导航堆栈不会更新。

这是我的UISearchController初始化代码:

override func viewDidLoad() {
    super.viewDidLoad()

    // Initialise search controller settings
    searchController = UISearchController(searchResultsController: nil)
    searchController.searchResultsUpdater = self
    searchController.searchBar.sizeToFit()
    searchController.dimsBackgroundDuringPresentation = false
    searchController.delegate = self
    searchController.searchBar.delegate = self
    tableView.tableHeaderView = searchController.searchBar
    definesPresentationContext = true
}

是否有实现此功能的技巧?

感谢。

2 个答案:

答案 0 :(得分:0)

我在iOS 9.0中的searchResultTableView中遇到了同样的错误。 我在searchResultTableView中调用unwind segue触发器,但它没有移动到destinationVC,即使我已成功将其数据传递到destinationVC。

我通过创建自定义展开segue解决了这个问题。

让我们来看看应用程序结构及其逻辑。结构将如下所示:

  

CustomNavigationController(UINavigationController的子类) - > MainVC - > push segue - > SearchVC(UISearchController的子类)

  1. MainVC嵌入在CustomNavigationController
  2. 如果从searchResultTableView中选择单元格, 应用程序使用unwind segue移动到MainVC。我认为你已经在故事板中放松了。因此,您可以设置数据以传递给destionationVC并在此方法中调用performSegueWithIdentifier方法。

    // SearchVC or SearchResultVC
    -(void)tableView:(UITableView *)tableView 
    didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    
        CustomData *customData = self.searchResults[[self.tableView indexPathForSelectedRow].row];
    
        self.selectedData = customData;
    
        [self performSegueWithIdentifier:@"PassResult" sender:nil];
    
        [tableView deselectRowAtIndexPath:indexPath animated:YES];
    
     }
    
  3. 在SearchVC中实现prepareForSegue:sender方法 SearchResultVC用于将数据传递到destinationVC(MainVC)

    -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
    
        if ([segue.identifier isEqualToString:@"PassResult"]) {
            MainVC *destVC = (MainViewController *)segue.destinationViewController;
            destVC.selectedData = self.selectedData;
        }
    }
    
  4. 使用performSegueWithIdentifier方法调用unwind segue时,请在导航控制器中移至rootVC。你有两种选择。使用展开segue方法或创建自定义segue。

  5.   

    展开segue方法

    如果您连接searchWithResult方法(在MainVC中)以展开segue标识PassResult

        - (IBAction)searchWithResult:(UIStoryboardSegue *)segue
        {
    
            [self.navigationController popToRootViewControllerAnimated:YES];
    
            // Add your code to process your custom data from unwind segue
            ....
        }
    
      

    自定义segue

    创建自定义segue并实施-perform方法。您可以添加自定义动画。我只想在这里转移到RootVC。​​

        @implementation CustomUnwindSegue
    
        - (void)perform
        {
    
            UIViewController *sourceViewController = (UIViewController *)self.sourceViewController;
            UIViewController *destinationViewController = (UIViewController *)self.destinationViewController;
    
            [destinationViewController.navigationController popToRootViewControllerAnimated:YES];
    
        }
    
        @end
    

    实现segueForUnwindingToViewController:fromViewController:CustomNavigationController中的identifier方法。无法根据推送或模态状态调用此方法,但它适用于此app结构。

        // refer to : http://hmcreation.net/?p=279
        -(UIStoryboardSegue *)segueForUnwindingToViewController:(UIViewController *)toViewController
                                         fromViewController:(UIViewController *)fromViewController
                                                 identifier:(NSString *)identifier{
            UIStoryboardSegue *segue;
    
            if ([identifier isEqualToString:@"PassResult"]) {
    
                segue = [[CustomUnwindSegue alloc]
                                        initWithIdentifier:identifier
                                        source:fromViewController
                                        destination:toViewController];
    
            }else{
    
                if ([super respondsToSelector:@selector(unwindForSegue:towardsViewController:)]) {
    
    
                    NSLog(@"unwinding in iOS9 later");
    
                    [super unwindForSegue:segue towardsViewController:toViewController];
    
                }
    
                NSLog(@"segueForUnwinding in iOS9 below");
    
                segue = [super segueForUnwindingToViewController:toViewController
                                      fromViewController:fromViewController
                                              identifier:identifier];
    
            }
    
            return segue;
    
        }
    

    在iOS9中,您可以在自定义navigationController中覆盖unwindForSegue:towardsViewController方法。该方法的文档描述了它可以处理弹出viewControllers以移动到目标。但看起来它在UISearchController中不起作用。

答案 1 :(得分:0)

我遇到了同样的问题,并且有我的解决方案和解释:当searchController.isActive = true时,它会自动将navigationController(包含searchController)推送到navigationController。因此,尝试从viewController展开到initialViewController,会出现您所描述的错误。要避免此问题,您必须先解除searchController。所以,改为使用这一行

performSegue(withIdentifier: "unwindSegueFromViewControllerToInitialViewController", sender: self)

你必须使用这个块:

if searchController.isActive {

  searchController.dismiss(animated: false, completion: {
    self.performSegue(withIdentifier: "unwindSegueFromViewControllerToInitialViewController", sender: self)
  })

} else {

  performSegue(withIdentifier: "unwindSegueFromViewControllerToInitialViewController", sender: self)

}