ios - 取消 View 后,UISegmentedControl消失

标签 ios iphone swift uitableview uisegmentedcontrol

在使用底部的TabBar,顶部的NavBar和分段控件的情况下使用此应用程序:

我有一个问题,其中带有UITableView的View A(第一个细分)在选择一个单元格并显示一个包含更多详细信息的新视图时,当我单击返回时,顶部的Segmented控件将消失并且View A中的TableView将变为推高了。

这并非总是会发生-有时经过多次尝试,有时仅一次尝试。我还没有发现任何相关原因。

我发现,如果我从分段控件中选择“视图B”,然后返回到“视图A”,然后单击一个表格单元格以进入“详细信息”屏幕,然后单击“返回”,那么“顶部导航栏”消失的时间为100%分段控件。

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)
}

最佳答案

顺便说一句漂​​亮的图形...该插图使您更容易理解您的问题。

顺便说一句,我是Obj-C的人,还在学习Swift的细微差别,所以请让我知道我的语法是否不正确。我在使用容器VC方面也相对缺乏经验。

我已将回复分为两部分。

第一部分是我试图解决您的问题。

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

第一部分

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

具有分段控件的父视图

  • public init ():在实例化父视图控制器时,实例化了两个子VC(segmentOneVC和segmentTwoVC),并根据先前的选择将其分配为currentViewController。然后,将分段控件添加到TabBarItemOneViewController
  • 用户点击一个分段控件。
  • 根据用户输入,将SegmentOneViewControllerSegmentTwoViewController视图添加为subviewTabBarItemOneViewController.view。 (请注意,在初始化VC时也会这样做。)

  • 儿童观
  • override func viewDidLoad():一旦加载了视图,就调用addTableView函数。
  • func addTableView():在此自定义函数中,您将实例化表视图并将其放置在SegmentOneViewController中,我自己假设它为UIViewController
  • override func viewDidAppear(_ animated: Bool):您调用自定义函数loadData并设置表视图数据源和委托。

  • 返回键
  • 用户点击后退按钮。
  • 儿童VC被关闭,并且TabBarItemOneViewController成为屏幕上的 Activity 视图。

  • 让我们看看按下后退按钮时视图控制器生命周期中没有发生什么……列表中的项目1。

    这可以解释不一致之处。

    试试这个...运行应用程序,点击选项卡控件,将您带到TabBarItemOneViewController。不要点击分段控件。在表格视图中点击一条线。在您的子VC中点击后退按钮。我猜想您的分段控件仍然存在。

    现在尝试这个...运行应用程序,点击选项卡控件,将您带到TabBarItemOneViewController。点击分段控件。在表格视图中点击一条线。在您的子VC中点击后退按钮。我猜想您的分段控件不再存在。

    为什么?因为我假设自定义函数pressedSegItem已将目标操作分配给分段控件,所以它将覆盖init,这是将分段控件添加到标签栏视图控制器中的位置。

    因此,作为示例,请尝试将代码实例化分段控件,而不是将其放置在viewWillAppear VC的TabBarItemOneViewController的覆盖函数中。

    所以要考虑几个概念...
  • 延迟加载以节省内存分配-仅当用户在应用程序中特别请求该功能时,才实例化所需的对象;
  • UIViewController生命周期中每个函数的执行顺序;和
  • 哪些函数执行一次,并且每次视图成为第一响应者/ Activity 视图时执行。

  • 一些阅读建议:
  • SO question titled :Looking to understand the iOS UIViewController lifecycle"提供了很多有用的信息,但要了解,由于iOS 6中弃用了viewDidUnload,因此某些信息是不正确的。
  • 这就是为什么您应该始终转到Apple documentation for UIViewController来引用最新的API参考的原因。

  • 第二部分

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

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

    考虑仅在一个表视图中使用UISegmentedControl来管理或调整数据集。这将减轻对多个视图控制器的需求以及管理这些视图控制器的麻烦。

    例如,当为表格视图编写数据源和委托方法/函数时,可以包含以下代码以确保表格视图加载并响应:
    let selectedIndex = segControl.selectedSegmentIndex
    if(selectedIndex == 0) {
        rowHeight = 20 'for example
    } else {
        rowHeight = 30 'for example
    }
    

    然后,您需要重新布局表视图以实现更改。

    关于ios - 取消 View 后,UISegmentedControl消失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44081069/

    相关文章:

    ios - 如何快速从 HTTP Get 获取状态码?

    ios - 如何将数组写入plist?

    ios - 在 UITabBarController 中,如何找出选项卡栏中的哪个 UIViewController 在 Swift 2.x 中显示当前的 UIViewController

    ios - 如何显示多个 UIImageView

    ios - 在 View Controller 之间传递对象

    Swift 可选的转义闭包

    iphone - UIImage - 实现自动级别算法

    iphone - 如何在 iOS 上做晕影效果?

    iphone - UIProgressView 不显示

    Swift:无法将类型 'Any' 的值分配给类型 'AnyObject?' 的值