子视图添加到导航栏下方的 UITableView 不正确的 Y 值

SubView Added to UITableView Below Navigation Bar Incorrect Y Value

我有一个嵌入在 UITabBarController 中的 UINavigationController 中的 UITableViewController。

我正在尝试添加子视图以在不满足条件时屏蔽导航栏和选项卡栏之间的区域,但我添加的子视图并不完全在正确的位置。它似乎向上移动了状态栏和导航栏组合的高度(注意阴影区域下方的间隙......也应该是阴影)。

以下是我尝试完成的方法:

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    setupLinks()
    addBlockViewIfRequired()
  }

  override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(animated)
    blockView.removeFromSuperview()
  }
  override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    setSizeOfBlockView()
  }

  func addBlockViewIfRequired() {
    if dataModel.getAccounts().isEmpty {
      if let navController = self.navigationController {
        blockView.backgroundColor = UIColor.blackColor()
        blockView.alpha = 0.5
        setSizeOfBlockView()
        navController.view.insertSubview(blockView, belowSubview: navController.navigationBar)
      }
    }
  }

  func setSizeOfBlockView() {
    let blockViewRect = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)
    blockView.frame = blockViewRect
  }

关于我需要调整什么才能正确放置此子视图,有什么想法吗?谢谢!


编辑: 这是直接修复:

  func setSizeOfBlockView() {
    if let navController = self.navigationController {
      let blockViewRect = CGRectMake(0, navController.navigationBar.frame.maxY, self.view.bounds.size.width, self.view.bounds.size.height)
      blockView.frame = blockViewRect
    }
  }

另一种方法:

  func setSizeOfBlockView() {
    if let navController = self.navigationController {
      var blockViewRect = self.view.bounds
      blockViewRect.origin.y = navController.navigationBar.frame.maxY
      blockView.frame = blockViewRect
    }
  }

我猜您的视图部分位于导航栏下方。您可以使用 UI 调试器仔细检查。

您需要将 blockViewRect.origin.y 设置到导航栏的底部,例如

let blockViewRect = CGRectMake(0, navigationController?.navigationBar.frame.maxY, self.view.bounds.size.width, self.view.bounds.size.height)

为了美化一下...

var blockViewRect = self.view.bounds
blockViewRect.origin.y = navigationController?.navigationBar.frame.maxY

仅供参考,正确的 navigationController 可能在您的 VC 的 parentViewControllers 之一中。

为什么要将此 blockingView 放入 导航控制器的 rootView

导航控制器应该完全不理会特定的业务上下文细节。修复很简单,但问题背后有一些基本的编程原则,所以请考虑一下。 要求是"show a blockView if the account is empty"。但是每一个需求都会带来一个问题 -> 谁应该负责处理这个需求?哪个entity/object?

架构软件基本上就是这些职责的划分。
在您的案例中,显示阻塞视图的正确负责实体是 viewController,即 in 导航控制器的堆栈。如果我可以从屏幕截图中假设,它就是显示 table 视图的视图。

所以不用这个

navController.view.insertSubview(blockView, belowSubview:navController.navigationBar)

我希望在各自的视图控制器中有一个私有的便捷方法

 setupBlockView() {

     //here you set up your view..everything (color, content, position in view hierachy..whatever) **except** layout (size and position)

    self.view.addSubView(blockView)

}

您从 viewDidLoad 而不是 viewDidAppear 调用此方法。据我所知,您有一个 blockView 属性 可以使视图保持活动状态。顺便说一句,应该是私人的。

接下来,在 viewWillAppear 中,您将使用一个非常简单的

blockView.hidden = model.account.isEmpty

很高兴看到有人使用 'layoutSubviews' 布局子视图 :) 但是一旦你应用了上面的更改..你的布局变得非常简单..摆脱便利方法并直接在布局子视图中说

blockView.frame = self.view.bounds

边界方法是正确的。您只想复制大小,而不是非零位置。 您是否注意到我们去掉了多少 行代码? :)