如何根据选定的单元格将segue推送到特定的View Controller?

时间:2017-12-19 09:01:12

标签: ios swift uitableview

我有一个复杂的问题,我想通过视觉和代码解释。

目前,这就是我的应用程序可视化工作的方式:

enter image description here

我有一个ViewControllerOne类,其中包含一个包含9个单元格的UITableView。选择第2行,第6行和第7行之外的任何行都将使用自己的ViewControllerTwo和行数转换为UITableView

如果选择了行2,6或7,则push segue会将另一个ViewControllerOne堆叠到现有ViewControllerOne上。这样做的原因是因为每一行都是一个类别,但第2,6和7行也包含与左侧的ViewControllerOne Main-VC 完全相同的子类别。 / p>

我想重用ViewControllerOne类,而不是创建另一个包含与 Main-VC 完全相同的代码的类。

现在,如果选择了 SUB-VC 中的任何行,则执行推送到ViewControllerTwo的行。

由于ViewControllerOneViewControllerTwo已嵌入UINavigationController,我所拥有的问题位于第5个步骤中:

  1. 我在 Main-VC 中选择 2,6或7行,我需要ViewControllerTwo(应该这样)
  2. 我通过导航栏后退按钮返回 Main-VC 并选择MAIN-VC中的第2,6或7行,我将转到SUB-VC(如它应该)
  3. 我在 Sub-VC 中选择 2,6或7行,它会转到ViewControllerTwo(应该这样)
  4. 我通过导航栏上的导航栏后退按钮返回 Sub-VC
  5. 我在 Sub-VC 中选择第2行,第6行或第7行,它将推送segue并在现有之上堆叠另一个 Sub-VC Sub-VC 而不是推送到ViewControllerTwo
  6. 我有一个Manager类来处理逻辑并与ViewControllerOneViewControllerTwo进行通信以显示数据。

    import UIKit
    
    enum SubGroupState
    {
        case SubGroup1, None, SubGroup2, SubGroup3
    }
    
    class Manager: NSObject
    {
        public var subGroupState = SubGroupState.None
        public var oldSubGroupState = SubGroupState.None
        public var showSubGroups = Bool()
    
        override init()
        {
            super.init()
        }
    
        public func initializeGroupState(row: Int) -> UIViewController
        {
            if showSubGroups == false && oldSubGroupState == .None
            {
                switch row
                {
                    case 2:
                        subGroupState = .SubGroup1
                        break
    
                    case 6:
                        subGroupState = .SubGroup2
                        break
    
                    case 7:
                        subGroupState = .SubGroup3
                        break
    
                    default:
                        subGroupState = .None
                        break
                }
            }
    
            if (subGroupState != .None && oldSubGroupState == .None)
                || (subGroupState == .None && oldSubGroupState != .None)
            {
                showSubGroups = true
            }
            else
            {
                showSubGroups = false
            }
    
            return initializeGroupVC(row: row)
        }
    
        fileprivate func initializeGroupVC(row: Int) -> UIViewController
        {
            let storyboard = UIStoryboard(name: "Main",
                                          bundle: nil)
    
            if showSubGroups == true
                && subGroupState != .None
            {
                guard let viewControllerOne = storyboard.instantiateViewController(withIdentifier: "ViewControllerOne")
                    as? ViewControllerOne else {
                    return UIViewController()
                }
                viewControllerOne.manager.oldSubGroupState = muscleSubGroupState
                viewControllerOne.manager.showSubGroups = showSubGroups
    
                return viewControllerOne
            }
            else
            {
                guard let viewControllerTwo = storyboard.instantiateViewController(withIdentifier: "ViewControllerTwo")
                    as? ViewControllerTwo else {
                    return UIViewController()
                }
    
                return muscleGroupExercisesVC
            }
        }
    
    }
    

    states的目的是让我可以处理根据所选单元格的state显示不同的子类别。

    当用户选择一个单元格时,我在Manager中创建了ViewControllerOne的实例:

    extension ViewControllerOne: UITableViewDataSource
    {
        func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
        {
            tableView.deselectRow(at: indexPath,
                                  animated: true)
    
            let viewController = manager.initializeGroupState(row: indexPath.row)
            self.navigationController?.pushViewController(viewController,
                                                          animated: true)
        }
    }
    
    class ViewControllerOne: UIViewController
    {
        public var manager = Manager()
    
        ....
    }
    

    问题在于函数initializeGroupState中的逻辑处理,但我尝试了其他不同的组合,并且总是将 Sub-VC 堆叠在现有的之上第2行,第6行和第7行的子VC ,显然对应于 Main-VC 中的子组行,这就是问题我处理逻辑时遇到的困难用。

    如果我这样做的方式不对,那么在不重复代码的情况下,是否有更好的替代方案?

    注意:我的Storboard只有 Main-VC ViewControllerOne且segue为ViewControllerTwo。添加的 Sub-VC ViewControllerOne可以直观地看到我正在尝试做的事情,但实际上并没有存在于我的故事板中。

4 个答案:

答案 0 :(得分:1)

我认为我们可以保持简单可行

class ViewControllerOne: UIViewController, UITableViewDelegate {
  var isSubVC = false

  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: false)

    if self.isSubVC {
      // Push to ViewControllerTwo
    } else {
      // MainVC
      if indexPath.row == 2 || indexPath.row == 6 || indexPath.row == 7 {
        let subVC = self.storyboard?.instantiateViewController(withIdentifier: "ViewControllerOne") as! ViewControllerOne
        subVC.isSubVC = true
        self.navigationController?.pushViewController(subVC, animated: true)
      } else {
        // Push to ViewControllerTwo
      }
    }
  }
}

以下是使用您的经理创意进行导航而无需任何测试的代码。

enum ViewControllerType {
  case main, subGroup1, subGroup2, subGroup3
}

class Manager {
  public var currentState = ViewControllerType.main

  public func initializeGroupState(row: Int) -> UIViewController {
    if self.currentState == .main {
      // MainVC, should push to SubVC if match condition
      switch row {
      case 2:
        return self.makeSubViewController(state: .subGroup1)
      case 6:
        return self.makeSubViewController(state: .subGroup2)
      case 7:
        return self.makeSubViewController(state: .subGroup3)
      default:
        return self.makeViewControllerTwo()
      }
    } else {
      // Current is SubVC, dont care kind of row, should push to ViewControllerTwo
      return self.makeViewControllerTwo()
    }
  }

  private func makeViewControllerTwo() -> UIViewController {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let vc = storyboard.instantiateViewController(withIdentifier: "ViewControllerTwo")
    return vc
  }

  private func makeSubViewController(state: ViewControllerType) -> UIViewController {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let vc = storyboard.instantiateViewController(withIdentifier: "ViewControllerOne") as! ViewControllerOne
    vc.manager.currentState = state
    return vc
  }
}

答案 1 :(得分:0)

OK!这里发生的是你有一些segues连接到你的tableView,当你在代码中推送一个新的视图控制器时,这会导致问题。

根据您在此处发布的代码,我认为只是从故事板中删除segue就可以解决问题。仅在您tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)中已经执行的代码中完成此操作非常好。

您可以通过单击它们并按退格键来删除segues,视图控制器可以在故事板中自行浮动而不通过segues连接。

答案 2 :(得分:0)

在Objective-C中,逻辑应该是相同的,这就是我要做的事情:

CustomModel:

@property (nonatomic, strong) NSArray *subdata;
@property (nonatomic, strong) NSString *title;
@property (nonatomic, assing) BOOL isSpecial; //of course wording should be adapted to the real logic and your needs

默认情况下,在CustomModel对象的init上,isSpecial设置为NO。

ViewControllers:

@property (nonatomic, strong), NSArray *tableViewDataSource;

tableViewDataSource的{​​{1}}应该是这样的:

MainViewController

决定下一个viewcontroller的逻辑: 你可以使用Segue或手动实例化/推送,但我建议你继续为这两个方法做同样的方法

- CustomData isSpecial: NO
             subdata = [CustomData11, CustomData12...] 
- CustomData isSpecial: NO
             subdata = [CustomData21, CustomData22...] 
- CustomData isSpecial: YES
             subdata = [CustomData31, CustomData32...] 
- CustomData isSpecial: NO
             subdata = [CustomData41, CustomData42...] 
- CustomData isSpecial: NO
             subdata = [CustomData51, CustomData52...] 
- CustomData isSpecial: NO
             subdata = [CustomData61, CustomData62...] 
- CustomData isSpecial: YES
             subdata = [CustomData71, CustomData72...] 
- CustomData isSpecial: YES
             subdata = [CustomData81, CustomData82...] 
- CustomData isSpecial: NO
             subdata = [CustomData91, CustomData92...] 

答案 3 :(得分:0)

您可以管理viewcontroller和manager类,如下所示:

class ViewControllerOne: UIViewController, UITableViewDelegate {
    var isSubVC = false

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: false)

        let wireframe = WireFrame()
        let nextVC = wireframe.getNextVC(forView: self)
        self.navigationController?.pushViewController(nextVC, animated: true)
    }
}

class WireFrame {

    func getNextVC (forView view: UIViewController) -> UIViewController {
        if view.isKind(of: ViewControllerOne) {
            return ViewControllerTwo
        } else {
            // MainVC
            if indexPath.row == 2 || indexPath.row == 6 || indexPath.row == 7 {
                let subVC = self.storyboard?.instantiateViewController(withIdentifier: "ViewControllerOne") as! ViewControllerOne
                subVC.isSubVC = true
                return subVC
            } else {
                return ViewControllerTwo
            }
        }
    }
}