解散视图后,UISegmented控件消失

时间:2017-05-20 01:40:13

标签: ios iphone swift uitableview uisegmentedcontrol

使用底部的TabBar处理此应用程序时,顶部的NavBar带有分段控件:

我遇到一个问题,其中带有UITableView的View A(Segment One),在选择一个单元格并显示一个包含更多细节的新视图时,当我单击后面时,顶部的Segmented控件将消失,TableView将从View中消失A会被推高。

这并不总是发生 - 有时经过多次尝试或有时只有一次。我没有发现导致它的相关性。

我发现如果我从分段控件中选择View B,然后返回View A,然后单击其中一个表格单元格以进入详细信息屏幕,然后单击返回,100%的时间使用Top Nav条形图随着分段控制而消失。

enter image description here

TabBarItemOneViewController

let segmentOneVC: SegmentOneViewController
let segmentTwoVC: SegmentTwoViewController

var currentViewController: UIViewController

let viewControllerYLoc = 60 // statusBarHeight + topBarHeight
let viewWidth = Helper.getViewWidth()
let tabBarHeight = 40

func pressedSegItem(segControl: UISegmentedControl){

    let viewControllerHeight = Int(self.view.frame.height)

    let viewFrame = CGRect(x: 0, y: viewControllerYLoc, width: Int(viewWidth), height: viewControllerHeight)

    let selectedIndex = segControl.selectedSegmentIndex
    previouslySelectedMyLoadsIndex = selectedIndex

    self.currentViewController.removeFromParentViewController()

    if(selectedIndex == 0){
        currentViewController = segmentOneVC
    }
    else if(selectedIndex == 1){
        currentViewController = segmentTwoVC
    }

    self.view.addSubview(self.currentViewController.view)
    self.currentViewController.didMove(toParentViewController: self)
}

public init() {

    segmentOneVC = SegmentOneViewController(nibName: nil, bundle: nil)
    segmentTwoVC = SegmentTwoViewController(nibName: nil, bundle: nil)

    if(previouslySelectedIndex == 0){
        currentViewController = segmentOneVC
    }
    else{
        currentViewController = segmentTwoVC
    }

    super.init(nibName: nil, bundle: nil)

    self.calculateItems()

    self.addSegmentedControl()

    let viewControllerHeight = (Int(self.view.frame.height) - viewControllerYLoc) - tabBarHeight

    let viewFrame = CGRect(x: 0, y: viewControllerYLoc, width: Int(viewWidth), height: viewControllerHeight)

    self.currentViewController.view.frame = viewFrame
    self.addChildViewController(segmentOneVC)
    self.addChildViewController(segmentTwoVC)
    self.view.addSubview(self.currentViewController.view)
    self.currentViewController.didMove(toParentViewController: self)
}

SegmentOneViewController (注意:SegmentTwoViewController完全相同)

let cellReuseIdentifier = "ItemDetailTableViewCell"

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let row = indexPath.row

    let dataItem = self.dataArray[row]

    let itemDetailVC = ItemDetailViewController()
    itemDetailVC.dataItem = dataItem
    self.present(itemDetailVC, animated: true, completion: nil)
}

func addTableView(){
    self.tableView = UITableView()

    tableView.register(ItemDetailTableViewCell.self, forCellReuseIdentifier: self.cellReuseIdentifier)

    tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)

    tableView.frame = CGRect(x: 0, y: 0, width: Int(viewWidth), height: (Int(self.view.frame.height) - bottomOfTopNavBar) - heightOfTabBar)

    self.view.addSubview(tableView)
}

override func viewDidAppear(_ animated: Bool){
    super.viewDidAppear(animated)

    loadData()

    tableView.dataSource = self
    tableView.delegate = self
}

override func viewDidLoad() {
    super.viewDidLoad()

    addTableView()
}

ItemDetailViewController

// Connected to a back button in a top Navigation Bar
func goBack(){
    self.dismiss(animated: false, completion: nil)
}

1 个答案:

答案 0 :(得分:1)

漂亮的图形BTW ......这个插图让你更容易理解你的问题。

同样顺便说一下,我是Obj-C的人,还在学习Swift的细微差别,所以如果我的语法或其他方面不正确,请告诉我。我在使用容器VC方面也相对缺乏经验。

我分两部分写了我的回复。

第一部分是我尝试解决你的问题。

第二部分是我建议您考虑的替代方案。

第一部分

这是我对代码中执行顺序/顺序的理解......

带分段控制的父视图

  1. public init ():在实例化父视图控制器时,实例化两个子VC(segmentOneVC和segmentTwoVC),并根据先前的选择分配为currentViewController。然后,您将分段控件添加到TabBarItemOneViewController

  2. 用户点按分段控件。

  3. 根据用户输入,SegmentOneViewControllerSegmentTwoViewController视图已添加为subview TabBarItemOneViewController.view。 (请注意,初始化VC时也会这样做。)

  4. 子视图

    1. override func viewDidLoad():视图加载后,您调用函数addTableView

    2. func addTableView():在这个自定义函数中,您实例化表视图并将其放在SegmentOneViewController中,而SegmentOneViewController本身就是UIViewController

    3. override func viewDidAppear(_ animated: Bool):您调用自定义函数loadData并设置表视图数据源和委托。

    4. 后退按钮

      1. 用户点按后退按钮。

      2. 子VC被关闭,TabBarItemOneViewController成为屏幕上的活动视图。

      3. 让我们看一下当按下后退按钮时视图控制器生命周期中没有发生的事情......列表中的项目1。

        这可以解释不一致。

        试试这个...运行应用,点按标签控件即可转到TabBarItemOneViewController。不要点击分段控件。点按表格视图中的一条线。点击孩子VC中的后退按钮。我猜测你的分段控制仍在那里。

        现在试试这个...运行应用,点按标签控件,转到TabBarItemOneViewController。点按分段控件。点按表格视图中的一条线。点击孩子VC中的后退按钮。我猜测你的分段控制不再存在了。

        为什么呢?由于我假设自定义函数pressedSegItem具有分配给分段控件的目标操作,因此将覆盖init,这是将分段控件添加到选项卡栏视图控制器中的位置。

        因此,举例来说,尝试放置代码以在viewWillAppear VC的TabBarItemOneViewController的覆盖函数中实例化分段控件。

        所以要考虑几个概念......

        • 延迟加载以节省内存分配 - 仅在用户明确请求应用程序中的该功能时实例化您需要的对象;
        • UIViewController生命周期中每个函数的执行顺序;和
        • 每次执行第一响应者/活动视图时执行一次并执行哪些功能。

        一些阅读建议:

        第二部分

        通过提供此替代方案,我并不是说您的方法不正确,但我建议您考虑另一种选择。

        我一直使用标签栏控制器来更改视图和分段控件来过滤数据集或更改当前视图的外观。

        考虑使用UISegmentedControl仅在一个表视图中管理或调整数据集。这将减少对多个视图控制器的需求以及管理这些操作的杂耍行为。

        例如,在为表单视图编写数据源和委派方法/函数时,可以包含以下代码以确保表视图加载并响应:

        let selectedIndex = segControl.selectedSegmentIndex
        if(selectedIndex == 0) {
            rowHeight = 20 'for example
        } else {
            rowHeight = 30 'for example
        }
        

        然后,您需要重新加载表格视图以实现更改。